1.线段树
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; int n,p,a,b,m,x,y,ans; struct node{ int l,r,w,f; }tree[100005]; void build(int l,int r,int o){ tree[o].l = l,tree[o].r = r; if(tree[o].l == tree[o].r) { scanf("%d",&tree[o].w); return; } int mid = (l+r)/2; build(l,mid,o*2); build(mid+1,r,o*2+1); tree[o].w = tree[o*2].w + tree[o*2+1].w; } void pushdown(int o){ tree[o*2].f += tree[o].f; tree[o*2+1].f += tree[o].f; tree[o*2].w += (tree[o*2].r-tree[o*2].l+1) * tree[o].f; tree[o*2+1].w += (tree[o*2+1].r-tree[o*2+1].l+1) * tree[o].f; tree[o].f = 0; } void change_point(int o){ if(tree[o].l == tree[o].r){ tree[o].w += y; return ; } if(tree[o].f) pushdown(o); int mid = (tree[o].l+tree[o].r)/2; if(x <= mid) change_point(o*2); else change_point(o*2+1); tree[o].w = tree[o*2].w + tree[o*2+1].w; } void query_point(int o){ if(tree[o].l == tree[o].r){ ans = tree[o].w; return ; } if(tree[o].f)pushdown(o); int mid = (tree[o].l + tree[o].r)/2; if(x <= mid) query_point(o*2); else query_point(o*2+1); } void query_interval(int o){ if(tree[o].l >= a && tree[o].r <= b){ ans += tree[o].w; return ; } if(tree[o].f)pushdown(o); int mid = (tree[o].l + tree[o].r)/2; if(a <= mid) query_interval(o*2); if(b > mid) query_interval(o*2+1); } void change_interval(int o){ if(tree[o].l >= a && tree[o].r <= b){ tree[o].w += (tree[o].r-tree[o].l+1) * y; tree[o].f += y; return; } if(tree[o].f)pushdown(o); int mid = (tree[o].l + tree[o].r)/2; if(a <= mid) change_interval(o*2); if(b > mid) change_interval(o*2+1); tree[o].w = tree[o*2].w + tree[o*2+1].w; } int main(){ scanf("%d",&n);scanf("%d",&m); build(1,n,1); for(int i=1;i<=m;i++) { scanf("%d",&p); ans=0; if(p==2) { scanf("%d%d",&a,&b); query_interval(1); printf("%d ",ans); } else { scanf("%d%d%d",&a,&b,&y); change_interval(1); } } return 0; }
2.树状数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int lowbit(int x){ return x & -x; } void add(int x,int y) { for(;x <= n;x += lowbit(x)) c[x] += y; } int query(int x) { int ans = 0; for(;x >= 1;x -= lowbit(x)) ans += c[x]; return ans; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ll c0[MAXN], c1[MAXN]; int lowbit(int x){ return x & -x; } void add(ll *c, int x, ll k) { for(; x <= N; x += lowbit(x)) c[x] += k; } ll sum(ll *c, int x) { ll r = 0; for(;x >= 1; x -= lowbit(x)) r += c[x]; return r; } void add(int l, int r, ll k) { add(c0, l, k); add(c0, r + 1, -k); add(c1, l, (l - 1) * k); add(c1, r + 1, -r * k); } ll sum(int l, int r) { return sum(c0, r) * r - sum(c1, r) - sum(c0, l - 1) * (l - 1) + sum(c1, l - 1); }
3.ST表
inline int query(int l,int r) { int tmp = lg[r-l+1]; return max(dp[l][tmp],dp[r-(1<<tmp)+1][tmp]); } inline void init() { for(register int i = 1;i <= n;i++) dp[i][0] = a[i]; for(register int j = 1;j < 21;j++) { for(register int i = 1;i+(1 << j-1) <= n;i++) { dp[i][j] = max(dp[i][j-1],dp[i+(1<<j-1)][j-1]); } } for(register int i = 2;i <= n;i++) lg[i] = lg[i >> 1]+1; }
4.并查集
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void init(int n){ for(int i = 0;i < n;i++) { father[i] = i; high[i] = 0; } } int find(int x){ if(father[x] == x) return x; else return father[x] = find(father[x]); } void uniue(int x,int y){ x = find(x); y = find(y); if(x == y) return; if(high[x] < high[y]) father[x] = y; else { father[y] = x; if(high[x] == high[y]) high[x]++; } } bool same(int x,int y){ return find(x) == find(y); }
5.队列、栈
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//数组实现 #include <cstdio> #define MAXN 2000005 using namespace std; struct Num{ int index,x;//需要记录单调队列内每个数的入队时间(index)和大小(x) }; int a[MAXN]; //原数组 Num q[MAXN]; //单调队列 int main(void){ int n,m; //n表示序列长度,m表示滑动窗口长度 int front,back; //front,back分别表示队头、队尾位置 //输入 scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); //问题解决 front=1; back=0;//初始化队头队尾位置,队头>队尾表示队空 for (int i=1;i<=n;i++){ //先输出数a[i]前的最小值 if (front>back) //q空,即a[i]前没有元素 printf("0 "); else { //否则判断队头是否需要出队并输出范围内的队头 if (q[front].index+m<i) //队头已经超出滑动窗口范围 front++; // 弹出队头 printf("%d ",q[front].x); //此时队一定非空(想想为什么) } while (front<=back && q[back].x>=a[i]) //当队列非空时,不断弹出队尾比当前元素大的元素 back--; back++; q[back].x=a[i]; q[back].index=i;//将当前元素入队 //注意:当前元素无论如何都会入队(想想为什么) } return 0; } //deque实现 #include <cstdio> #include <queue> // 提供deque #define MAXN 2000005 using namespace std; struct Num{ int index,x;//需要记录单调队列内每个数的入队时间(index)和大小(x) }; int a[MAXN]; //原数组 deque<Num> q; //单调队列 int main(void){ int n,m; //n表示序列长度,m表示滑动窗口长度 Num t;//保存当前元素 //输入 scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); //问题解决 for (int i=1;i<=n;i++){ //先输出数a[i]前的最小值 if (q.empty()) //q空,即a[i]前没有元素 printf("0 "); else { //否则判断队头是否需要出队并输出范围内的队头 if (q.front().index+m<i) //队头已经超出滑动窗口范围 q.pop_front(); // 弹出队头 printf("%d ",q.front().x); //此时队一定非空(想想为什么) } while ((!q.empty()) && q.back().x>=a[i]) //当队列非空时,不断弹出队尾比当前元素大的元素 q.pop_back(); t.index=i; t.x=a[i]; q.push_back(t);//将当前元素入队 //注意:当前元素无论如何都会入队(想想为什么) } return 0; }