POJ3468 A Simple Problem with Integers(线段树延时标记)
题目地址http://poj.org/problem?id=3468
题目大意很简单,有两个操作,一个
Q a, b 查询区间[a, b]的和
C a, b, c让区间[a, b] 的每一个数+c
第一次线段树的延时标记,花了好大的功夫才写好==!
很容易看出来使用使用线段树记录区间的和,但是难点在于每次修改的是一个区间而不是一个点
所以采用的方法就是每次做修改操作时,只将区间[a,b]的标记+c,而不是真正意义上的将区间[a, b] 的每一个值+c。
而当我们做查询操作时,就只需要将区间[a, b]在从[1, N]开始查找到查找到时所经过的区间的标记往下传递就可以了(同时记得更新当前节点的值)
1 #include <map> 2 #include <set> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <vector> 8 #include <cstdio> 9 #include <cctype> 10 #include <cstring> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 #define INF 0x3f3f3f3f 16 #define mem0(a) memset(a,0,sizeof(a)) 17 #define mem1(a) memset(a,-1,sizeof(a)) 18 #define lson k<<1, L, mid 19 #define rson k<<1|1, mid+1, R 20 21 typedef long long LL; 22 const double eps = 1e-12; 23 const int MAXN = 100005; 24 const int MAXM = 500005; 25 26 struct Node { LL sum, add; } tree[MAXN<<2]; 27 int a, b, N, Q; 28 LL c; 29 30 void updataChild(int k, int L, int R)//将编号为k的标记传到他的子节点去 31 { 32 tree[k].sum += (R-L+1) * tree[k].add;//先更新它自己的sum值 33 tree[k<<1].add += tree[k].add;//将左右子节点的add值更新 34 tree[k<<1|1].add += tree[k].add; 35 tree[k].add = 0;//去掉标记 36 } 37 38 void update(int k, int L, int R)//更新区间的值 39 { 40 if(R<a || b<L) return ;//不再区间内 41 42 if(a<=L && R<=b) { tree[k].add += c; return; }//实际上只更新这个区间的add值 43 44 int mid = (L+R)>>1; update(lson); update(rson); //往左和往右更新 45 46 tree[k].sum = tree[k<<1].sum + tree[(k<<1)+1].sum//更新当前节点的sum 47 + (mid-L+1)*tree[k<<1].add + (R-mid)*tree[k<<1|1].add; 48 } 49 50 LL query(int k, int L, int R) 51 { 52 if(R<a || b<L) return 0; 53 54 if(a<=L && R<=b) return tree[k].sum + (R-L+1)*tree[k].add;//注意加上当前节点的标记 55 56 int mid = (L+R)>>1; updataChild(k, L, R);//吧标记传到子节点 57 58 return query(lson) + query(rson); 59 } 60 61 int main() 62 { 63 while(~scanf("%d %d", &N, &Q)) 64 { 65 mem0(tree); char ch; 66 for(a=1;a<=N;a++) 67 { 68 scanf("%lld%*c", &c); b = a;//区间是[a, a] 69 update(1, 1, N); 70 } 71 for(int i=0;i<Q;i++) 72 { 73 scanf("%c", &ch); 74 if(ch == 'Q') 75 { 76 scanf("%d %d%*c", &a, &b); 77 printf("%lld\n", query(1,1,N)); 78 } 79 else 80 { 81 scanf("%d %d %lld%*c", &a, &b, &c); 82 update(1,1,N); 83 } 84 } 85 } 86 return 0; 87 }