hdoj 1698--Just a Hook 线段树练习
来源:互联网 发布:达芬奇调色 mac 编辑:程序博客网 时间:2024/06/10 20:38
/***********************************************Copyright:GlderAuthor:GlderDate:2013-08-03 14:54:46Destription: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 154、注意更新操作中要有注意更新时需要从父节点到子节点,这是此题要重点理解的内容。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)); }}