/*********************************************** Copyright:Glder Author:Glder Date:2013-08-03 14:54:46 Destription: 1、插线问题(成段更新) 2、建树结构体中是需要多加个元素权值 3、建树操作中注意 A: if(l == r) { s[root].num = 1; s[root].x = 0; cout<<"root: "<<root<<endl; return; } 如果这样写,不能把所有s[root].x都更新一遍,出现wa; 只需把s[root].x = 0;提到if语句外面即可ac,因为最后 有个pushup语句可以保证能把每个num都更新到。 B: s[root].num = 1; s[root].x = 0; cout<<"root: "<<root<<endl; if(l == r) { return; } 如果这样写,建树顺序如下: root:1 2 4 8 16 17 9 5 10 11 3 6 12 24 25 13 7 14 15 4、注意更新操作中要有注意更新时需要从父节点到子节点, 这是此题要重点理解的内容。 5、本题最后需要查询全部值的和,可以直接输出s[1].num, 也可以直接使用query(1,1,n); ***********************************************/ #include<iostream> #include<cstdio> using namespace std; struct Segtree { int left; int right; int num; int x;//权值 }s[100005<<2]; void build(int root,int l,int r) { s[root].left = l; s[root].right = r; s[root].x = 0; if(l == r) { s[root].num = 1; return; } int m = (l+r)/2; build(root<<1,l,m); build(root<<1|1,m+1,r); s[root].num = s[root<<1].num + s[root<<1|1].num; } void update(int root,int a,int b,int x) { int l = s[root].left; int r = s[root].right; if(a <= l && b >= r) { s[root].num = x*(r-l+1); s[root].x = x; return; } if(s[root].x)//把当前节点信息更新到叶子节点 { int p = r - l + 1; s[root<<1].x = s[root].x; s[root<<1|1].x = s[root].x; s[root<<1].num = (p - p/2)*s[root].x; s[root<<1|1].num = (p/2)*s[root].x; s[root].x = 0; } int m = (l + r)>>1; if(a <= m) update(root<<1,a,b,x); if(b > m) update(root<<1|1,a,b,x); s[root].num = s[root<<1].num + s[root<<1|1].num; } int query(int root,int a,int b) { int l = s[root].left; int r = s[root].right; if(a == l && b == r) return s[root].num; int m = (l + r) >> 1; int cnt = 0; if(a <= m) cnt += query(root<<1,a,b); if(b > m) cnt += query(root<<1|1,a,b); return cnt; } int main() { int t,n,q; int x,y,c; scanf("%d",&t); int cas = 1; while(t--) { scanf("%d",&n); build(1,1,n); scanf("%d",&q); while(q--) { scanf("%d%d%d",&x,&y,&c); update(1,x,y,c); } printf("Case %d: The total value of the hook is %d.\n",cas++,query(1,1,n)); } }