publicstaticvoidquickSort(int[] q, int l, int r) { if (l >= r) return; //(l+r)>>相当于l+r/2 intx= q[(l+r)>>1];
//Define positions of two pointers inti= l - 1; intj= r + 1;
while (i < j) { do i++; while (q[i] < x); do j--; while (q[j] > x); //do Swap if (i < j) { inttemp= q[i]; q[i] = q[j]; q[j] = temp; } }
quickSort(q, l, j); quickSort(q, j + 1, r); }
1 2 3 4 5 6 7 8 9 10 11 12 13
voidquick_sort(int q[], int l, int r) { if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + r >> 1]; while (i < j) { do i ++ ; while (q[i] < x); do j -- ; while (q[j] > x); if (i < j) swap(q[i], q[j]); } quick_sort(q, l, j), quick_sort(q, j + 1, r); }
归并排序
基本思想:
确定分界点x:q[l+r/2]。
递归排序左右。
归并—-合二为一。
代码模板如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
int temp[N]; publicstaticvoidmerge_sort(int[] a,int l, int r) { if (l >= r) return; intmid= l+r>>1; merge_sort(l, mid), merge_sort(mid+1, r); intk=0, i = l, j = mid+1; while (i <= mid && j <= r) { if (a[i] < a[j]) temp[k ++ ] = a[i ++ ]; else temp[k ++ ] = a[j ++ ];
} while (i <= mid) temp[k ++ ] = a[i ++ ]; while (j <= r) temp[k ++ ] = a[j ++ ]; for (inti= l, j = 0; i <= r; i ++ , j ++ ) a[i] = temp[j]; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
voidmerge_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]; }
二分查找
二分的本质是边界问题。
整数二分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
intlower_bound(int A[], int l, int r, int x) { int mid = l + r >> 1; while (l < r) { if (A[mid] >= x) { r = mid; } else { l = mid + 1; } } return l; }
浮点数二分:
1 2 3 4 5 6 7 8 9 10 11 12 13
boolcheck(double x){/* ... */} // 检查x是否满足某种性质
doublebsearch_3(double l, double r) { constdouble eps = 1e-6; // eps 表示精度,取决于题目对精度的要求 while (r - l > eps) { double mid = (l + r) / 2; if (check(mid)) r = mid; else l = mid; } return l; }
intmain(){ string a; int b; vector<int> A; cin>>a>>b;// a= "123456" for(int i =a.size()-1;i>=0;i--){ A.push_back(a[i]-'0'); } int r; auto C = div(A,b,r); for(int i =C.size()-1;i>=0;i--){ printf("%d",C[i]); } cout<<endl; cout<<r<<endl; return0; }
前缀和与差分
前缀和
假设一个数组为[a1,a2,...,an],求其前缀和Si=a1+a2+...+ai其中S0=0
如何求Si:S[i]=S[i-1]+a[i]
作用是能快速求出原数组中一段数的和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
constint N =100010; int n,m; int a[N],s[N]; cin>>n>>m; for(int i =1;i<=n;i++){ cin>>a[i]; } for(int i =1;i<=n;i++){ s[i]=s[i-1]+a[i]; } while(m--){ int l,r; cin>>l>>r; cout<<s[r]-s[l-1]; }
// 二分求出x对应的离散化的值 intfind(int x)// 找到第一个大于等于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; // 映射到1, 2, ...n }
int st = -2e9, ed = -2e9; for (auto seg : segs) if (ed < seg.first) { if (st != -2e9) res.push_back({st, ed}); st = seg.first, ed = seg.second; } else ed = max(ed, seg.second);