线段树
区间修改与求和
给出数的个数n以及操作数q:
对于q:
1 x y z 令区间[x, y]增加z
2 x y 求区间和
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define LL long long 5 using namespacestd; 6 const int maxn=1e5+10; 7 intn, q; 8 LL a[maxn]; 9 LL sum[maxn<<2], li[maxn<<2]; 10 11 void _push_up(intrt) { 12 sum[rt]=sum[rt<<1]+sum[(rt<<1)|1]; 13 }//向上更新,求区间和 14 15 void _setup(int l, int r, intrt) { 16 li[rt]=0; 17 if(l==r){ 18 sum[rt]=a[l]; 19 return; 20 } 21 int mid=(l+r)>>1; 22 _setup(l, mid, rt<<1); 23 _setup(mid+1, r, (rt<<1)|1); 24 _push_up(rt); 25 }//建树 26 27 void _push_down(int rt, intm) { 28 if(li[rt]) { 29 li[rt<<1]+=li[rt]; 30 li[(rt<<1)|1]+=li[rt]; 31 sum[rt<<1]+=li[rt]*(m-(m>>1)); 32 sum[(rt<<1)|1]+=li[rt]*(m>>1); 33 li[rt]=0; 34 } 35 }//将li标记向下更新,传递给小区间 36 37 void _add(int x, int y, LL z, int l ,int r, intrt) { 38 if(x<=l && y>=r) { 39 li[rt]+=z; 40 sum[rt]+=z*(r-l+1); 41 return; 42 } 43 _push_down(rt, r-l+1); //边算边更新,节省复杂度 44 int mid=(l+r)>>1; 45 if(x<=mid) _add(x, y, z, l, mid, rt<<1); 46 if(y>mid) _add(x, y, z, mid+1, r, (rt<<1)|1); 47 _push_up(rt); 48 } 49 50 LL _query(int x, int y, int l, int r, intrt) { 51 if(x<=l && y>=r) { 52 returnsum[rt]; 53 } 54 _push_down(rt, r-l+1); //求和时再顺便更新一次 55 int mid=(l+r)>>1; 56 LL ans=0; 57 if(x<=mid) ans+=_query(x, y, l, mid, rt<<1); 58 if(y>mid) ans+=_query(x, y, mid+1, r, (rt<<1)|1); //'夹'区间 59 returnans; 60 } 61 62 intmain() { 63 scanf("%d%d", &n, &q); 64 for(int i=1; i<=n; i++) { 65 scanf("%lld", a+i); 66 } 67 _setup(1, n, 1); 68 for(int i=0; i<q; i++) { 69 intls; 70 scanf("%d", &ls); 71 if(ls==1) { 72 intx, y; 73 LL z; 74 scanf("%d%d%lld", &x, &y, &z); 75 _add(x, y, z, 1, n, 1); 76 } else if(ls==2) { 77 intx, y; 78 scanf("%d%d", &x, &y); 79 printf("%lld ", _query(x, y, 1, n ,1)); 80 } 81 } 82 return 0; 83 }
区间最大值
描述:第1行给出数的个数n,操作数m
第2行为n个数
第3到m+3-1行有两个数a,b,求区间[a,b]中的最大数
样例:
Input
8 8
9 3 1 7 5 6 0 8
1 6
1 5
2 7
2 6
1 8
4 8
3 7
1 8
Output
9
9
7
7
9
8
7
9
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define CL(X,N) memset(X, N, sizeof(X)) 5 #define LL long long 6 #define ls root<<1 7 #define rs root<<1|1 8 using namespacestd; 9 const int maxn=1e5+10; 10 intn, m; 11 int a[maxn], t[maxn<<2]; 12 13 void _pushup(introot) { 14 t[root]=max(t[ls], t[rs]); 15 } 16 17 void _set(int l, int r, introot) { 18 if(l==r) { 19 t[root]=a[l]; 20 return; 21 } 22 int mid=(l+r)>>1; 23 _set(l, mid, ls); 24 _set(mid+1, r, rs); 25 _pushup(root); 26 } 27 28 int _query(int l, int r, int root, int a, intb) { 29 if(a<=l && b>=r) { 30 returnt[root]; 31 } 32 int mid=(l+r)>>1, ans=0; 33 if(a<=mid) ans=_query(l, mid, ls, a, b); 34 if(b>mid) ans=max(ans, _query(mid+1, r, rs, a, b)); 35 returnans; 36 } 37 38 intmain() { 39 scanf("%d%d", &n, &m); 40 for(int i=1; i<=n; i++) { 41 scanf("%d", a+i); 42 } 43 _set(1, n, 1); 44 for(int i=0; i<m; i++) { 45 inta, b; 46 scanf("%d%d", &a, &b); 47 printf("%d ", _query(1, n, 1, a, b)); 48 } 49 return 0; 50 }
指针版:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define CL(X,N) memset(X, N, sizeof(X)) 5 #define LL long long 6 using namespacestd; 7 const int maxn=1e5+10; 8 intn, m; 9 inta[maxn]; 10 structBit { 11 intl, r, data; 12 Bit *ls, *rs; 13 Bit(){ 14 l=0, r=0, data=0; 15 ls=rs=NULL; 16 } 17 }*t; 18 19 #define lc root->ls 20 #define rc root->rs 21 void _pushup(Bit *root) { 22 root->data=max(lc->data, rc->data); 23 } 24 25 void _set(int l, int r, Bit *root) { 26 root->l=l; 27 root->r=r; 28 if(l==r) { 29 root->data=a[l]; 30 return; 31 } 32 if(!lc) lc=newBit; 33 if(!rc) rc=newBit; 34 int mid=(l+r)>>1; 35 _set(l, mid, lc); 36 _set(mid+1, r, rc); 37 _pushup(root); 38 } 39 40 int _query(Bit *root, int a, intb) { 41 if(!root) return 0; 42 int l=root->l, r=root->r; 43 if(a<=l && b>=r) { 44 return root->data; 45 } 46 int mid=(l+r)>>1, ans=0; 47 if(a<=mid) ans=_query(lc, a, b); 48 if(b>mid) ans=max(ans, _query(rc, a, b)); 49 returnans; 50 } 51 52 intmain() { 53 t=newBit; 54 scanf("%d%d", &n, &m); 55 for(int i=1; i<=n; i++) { 56 scanf("%d", a+i); 57 } 58 _set(1, n, t); 59 for(int i=0; i<m; i++) { 60 intx, y; 61 scanf("%d%d", &x, &y); 62 printf("%d ", _query(t, x, y)); 63 } 64 return 0; 65 }
为什么写指针?
因为不容易MLE(不存在访问无效内存),但是写起来会需要小心一点