ACWing
0x01 排序 快排模板 1 2 3 4 5 6 7 8 9 10 11 12 #include <bits/stdc++.h> void quick_sort (int a[], int l, int r) { if (l>=r) return ; int i = l-1 , j = r+1 , x = a[l+r >>1 ] ; while (i<j){ do i++ ;while (a[i]<x) ; do j-- ;while (a[j]>x) ; if (i<j) swap (a[i],a[j]) ; } quick_sort (a,l,j),quick_sort (a,j+1 ,r); }
快排题目785 (简单数组排序) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <bits/stdc++.h> #define MAX_SIZE 100002 using namespace std ;int n ;int a[MAX_SIZE];void quick_sort (int a[],int l ,int r) { if (l>=r) return ; int i = l-1 , j = r+1 , x = a[l+r >>1 ] ; while (i<j){ do i++ ;while (a[i]<x) ; do j-- ;while (a[j]>x) ; if (i<j) swap (a[i],a[j]) ; } quick_sort (a,l,j),quick_sort (a,j+1 ,r) ; } void print (int a[],int n) { for (int i=1 ; i<=n;i++) cout<<a[i]<<" " ; } int main () { cin >> n ; for (int i=1 ; i<=n; i++){ cin >> a[i] ; } quick_sort (a,1 ,n) ; print (a,n); return 0 ; }
归并模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 void merge_sort (int q[], int l, int r) { if (l >= r) return ; int mid = l + r >> 1 ; merge_sort (q, l, mid); merge_sort (q, mid + 1 , r); int k = 0 , i = l, j = mid + 1 ; while (i <= mid && j <= r) { if (q[i] <= q[j]) tmp[k++] = q[i++]; else tmp[k++] = q[j++]; } while (i <= mid) tmp[k++] = q[i++]; while (j <= r) tmp[k++] = q[j++]; for (i = l, j = 0 ; i <= r; i++, j++) q[i] = tmp[j]; }
归并习题 788逆序对数量 思想:分治
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <bits/stdc++.h> using namespace std ;typedef long long LL ;const int MAX_SIZE = 100010 ;int a[MAX_SIZE],tmp[MAX_SIZE];LL merge_sort (int a[], int l, int r) { if (l>=r) return 0 ; int mid = l+r >> 1 ; LL res = merge_sort (a,l,mid) + merge_sort (a,mid+1 ,r) ; int k=0 , i=l, j = mid+1 ; while (i<=mid && j<=r){ if (a[i]<=a[j]) tmp[k++] = a[i++] ; else { tmp[k++] = a[j++] ; res += mid-i+1 ; } } while (i<=mid) tmp[k++] = a[i++] ; while (j<=r) tmp[k++] = a[j++] ; for (int i=l, j=0 ; i<=r; i++,j++) a[i] = tmp[j] ; return res ; } int main () { int n ; cin >> n ; for (int i=0 ; i<n; i++) { cin >> a[i] ; } cout<<merge_sort (a,0 ,n-1 ) ; return 0 ; }
0x02 二分 整数二分 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 bool check (int x) {} int SL (int l, int r) { while (l<r) { int mid = l+r >> 1 ; if (check (mid)) r=mid ; else l = mid+1 ; } return l ; } int SR (int l, int r) { while (l<r) { int mid = l+r+1 >> 1 ; if (check (mid)) l = mid ; else r = mid - 1 ; } return l ; }
789数的范围 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <bits/stdc++.h> #define MAX_SIZE 100010 using namespace std ;int a[MAX_SIZE] ;int SL (int l, int r, int x) { while (l<r){ int mid = l+r >>1 ; if (a[mid]>=x) r=mid ; else l = mid+1 ; } return l ; } int SR (int l, int r, int x) { while (l<r){ int mid = l+r+1 >> 1 ; if (a[mid]<=x) l=mid ; else r = mid-1 ; } return r ; } int main () { int n, q ; cin >> n >> q ; for (int i=0 ; i<n; i++) cin>>a[i] ; for (int i=0 ; i<q; i++){ int k ; cin >> k ; int l = SL (0 ,n-1 ,k) ; if (a[l]!=k) cout<<"-1 -1" <<endl ; else cout<<l<<" " <<SR (0 ,n-1 ,k)<<endl ; } return 0 ; }
浮点数二分 1 2 3 4 5 6 7 8 9 10 11 double S (double l, double r) { const double eps = 1e-6 ; while (r-l>eps){ double mid = (l+r)/2 ; if (check (mid)) r = mid ; else l = mid ; } return l ; }
790开三次方根 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <bits/stdc++.h> using namespace std ;int main () { double n ; cin>>n; double l = -10000 , r = 10000 ; while (r-l>1e-8 ){ double mid = (l+r)/2 ; if (mid*mid*mid >=n) r=mid ; else l=mid ; } printf ("%.6lf" ,l); return 0 ; }
0x03 双指针 最普遍模板
1 2 3 4 for (i=0 ,j=0 ;i<=n; i++){ while (j<i && check (i,j)) j++ ; }
思想核心:先想朴素的暴力算法,再将 简化为
799最长连续不重复子序列 最清晰题解链接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> #include <string.h> #include <algorithm> #define MAX_SIZE 100000 int a[MAX_SIZE] ;int s[MAX_SIZE] ;using namespace std ;int main () { int n ; int res = 0 ; cin >> n ; for (int i=0 ; i<n; i++) cin>>a[i] ; for (int i=0 ,j=0 ; i<n; i++){ s[a[i]]++ ; while (s[a[i]]>1 ){ s[a[j]]-- ; j++ ; } res = max (res,i-j+1 ) ; } cout<<res<<endl ; return 0 ; }
800 数组元素目标和 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> const int N = 100010 ;int a[N] ;int b[N] ;using namespace std ;int main () { int n,m,x ; cin >> n >> m >> x ; for (int i=0 ; i<n; i++) cin >> a[i] ; for (int i=0 ; i<m; i++) cin >> b[i] ; for (int i=0 ,j=m-1 ; i<n; i++){ while (j>=0 && a[i]+b[j]>x){ j--; } if (a[i]+b[j]==x){ cout<<i<<" " <<j<<endl; break ; } } return 0 ; }
2816判断子序列 子序列: 是 一个子序列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <iostream> const int N = 100010 ;int a[N]; int b[N];using namespace std ;int main () { int n, m ; cin >> n>> m ; for (int i=0 ; i<n; i++)cin>>a[i] ; for (int j=0 ; j<m; j++)cin>>b[j] ; int i=0 ; for (int j=0 ; j<m;j++){ if (i<n && a[i]==b[j]) i++ ; } if (i==n) cout<<"Yes" <<endl ; else cout<<"No" <<endl ; return 0 ; }
0x04 位运算 1 2 3 4 5 6 7 8 9 10 n>>k & 1 int lowbit (int x) { return x & -x ; }
801 二进制中1的位数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <iostream> #include <string> using namespace std ;const int N = 100010 ;int a[N] ;int lowbit (int x) { return x& -x ; } int main () { int n ; cin>>n ; while (n--){ int x ; cin>>x ; int res = 0 ; while (x) x -= lowbit (x) , res++ ; cout<<res<<" " ; } return 0 ; }
0x05 离散化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 vector<int > alls; sort (alls.begin (), alls.end ()); alls.erase (unique (alls.begin (), alls.end ()), alls.end ()); int find (int x) { int l = 0 , r = alls.size () - 1 ; while (l < r) { int mid = l + r >> 1 ; if (alls[mid] >= x) r = mid; else l = mid + 1 ; } return r + 1 ; }
vector:单端数组,与普通数组区别在于 vector 可以动态拓展 ,其迭代器支持随机访问,常用的有 v.begin(), v.end()
v.begin()返回第一个元素的位置,v.end()返回
动态拓展:找更大的内存空间,将原有数据COPY到新空间并释放原空间。
1 2 3 4 vector<T> v ; vector (v.begin (),v.end ()); vector (n,elem); vector (const vector &vec);