排序
快排
void quick_sort(int q[], int l, int r){
if(l>=r) return; //只有一个数据 或者递归返回条件
int x = q[l] , i = l-1, j = 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);
}
// 寻找第k小的数字
int quick_sort(int l, int r, int k){
if(l==r) return q[l];
int x = q[l] , i=l-1, j=r+1;
while(i<j){
do i++; while(q[i]<x);
do j--; while(q[i]>x);
if(i<j) swap(q[i], q[j]);
}
int s1 = j-l+1;
if(k <= s1) return quick_sort(l, j, k);
return quick_sort(j+1, r, k - s1);
}
归并排序
int tmp[N];
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 i = l, j = mid + 1, k = 0;
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++];
// 注意i的范围是 [l, r] , r是包含的
for(int i = l, j = 0; i <= r; i++,j++) q[i] = tmp[j];
}
// 求逆序对个数
LL merge_sort(int l, int r){
if(l>=r) return 0;
int mid = l + r >> 1;
LL res = merge_sort(l, mid) + merge_sort(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++];
res += mid - i + 1;
}
}
while(i<=mid) tmp[k++] = q[i++];
while(j<=r) tmp[k++] = q[j++];
for(int i=l,j=0; i<=r; i++,j++) q[i] = tmp[j];
return res;
}
堆排序
/*
规则:小根堆(顶点是小于左右两个子节点)
插入一个数 heap[++size] = x; up(size)
求集合中的最小值 heap[1]
删除最小值 heap[1] = heap[size--] down(1)
删除任意一个元素 heap[k] = heap[size--] 值变小,往上走;值变大,往下走 down(k),up(k);
修改任意一个元素 heap[k] = x ; down(k),up(k);
输入一个长度为n的整数数列,从小到大输出前m小的数。 大根堆:升序
*/
int h[N],size;
void down(int u){
int t = u;
if(u * 2 <= size && h[u * 2] < h[t]) t = u * 2;
if(u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
if(u != t){ // 非叶子节点
swap(h[u], h[t]);
down(t);
}
}
for(int i = 1; i <= n; i++) cin>>h[i];
size = n;
// 构建大根堆:从下往上构建,而且是从非叶子节点开始
for(int i = n/2; i; i--) down(i);
while(m--){
cout << h[1];
// 删除根节点,并更新堆
h[1] = h[size--];
down(1);
}
二分 (一个应用求三次开根)
// 右边部分
int l = 0, r = n-1;
while(l < r){
int mid = l + r >> 1;
if(q[mid] >= x) r = mid;
else l = mid + 1;
}
// 左边部分
while(l < r){
int mid = l + r + 1 >> 1;
if(q[mid] <= x) l = mid;
else r = mid - 1;
}
前缀和
for(int i = 1; i <= n; i++) s[i] = s[i-1] + a[i];
// 二维
for(int i = 1;i <= n; i++)
for(int j = 1;i <= m; j++)
s[i][j] = s[i][j-1] + s[i-1][j] - s[i-1][j-1] + a[i][j]; // 求前缀和
printf("%d\n", s[x2][y2] - s[x2][y1] - s[x1][y2] + s[x1][y1] - 1); // 算子矩阵的和
差分
void insert(int l, int r, int c){
b[l] += c; // 拉高起点
b[r+1] -= c; // 距离拉大
}
for(int i = 1; i <= n; i++) insert(i, i, a[i]);
while(m--){
int l, r, c;
scanf("%d%d%d", &l,&r,&c);
insert(l,r,c);
}
for(int i = 1; i <= n; i++) b[i] += b[i-1]; // 前边只要有一个数字加了,那么就会影响后边
// 二维差分矩阵
void insert(int x1, int y1, int x2, int y2, int c){
b[x1][y1] += c;
b[x2+1][y2+1] += c;
b[x1][y2+1] -= c;
b[x2+1][y1] -= c;
}
insert(i, j, i, j, a[i][j]);
insert(x1,y1,x2,y2,c);
for(int i = 1; i <= n; i++)
for(int j = 1;j <= m; j++)
b[i][j] = b[i-1][j] + b[i][j-1] - b[i-1][j-1] + b[i][j]; // 前缀和
双指针
同向双指针,异向双指针,快慢指针,距离为k的指针
/*
给定两个升序排序的有序数组A和B,以及一个目标值x。数组下标从0开始。
请你求出满足A[i] + B[j] = x的数对(i, j)。
*/
for(int i=0; i<n; i++){
while(j >= 0 && a[i] + b[j] > x) j--;
if(a[i] + b[j] == x) printf("%d %d\n", i, j);
// a[i]+b[j] < x 则i继续移动,所以就不再需要写代码
}