hdu1698(线段树懒惰法)
http://acm.hdu.edu.cn/showproblem.php?pid=1698
大意:给一组棍子染色,不同的颜色有不同的值,执行一系列的区间染色后,问这组棍子的总值是多少。
题目分析:建树:节点的域有左右节点和颜色,l,r,num;num=0时表示这个区间由多种颜色覆盖。
更新的时候,如果更新区间比当前区间小,并且当前区间的颜色大于0,说明已经被完全染色,就把该区间颜色传递到左右子树上,该区间染色为0,然后根据更新区间的大小,在左右子树上去搜索。
求和的时候遇到区间的num>0的时候说明完全被染色过了,就把区间的长度乘以颜色的值加到总和里面去,然后结束这个方向的递归查询,
代码:
#include<iostream> using namespace std; struct node { int l,r,num; }tree[400000]; int ans; void build(int i,int l,int r) { tree[i].l=l; tree[i].r=r; tree[i].num=1; if(l==r) return; else { int mid=(l+r)/2; build(i*2,l,mid); build(i*2+1,mid+1,r); } } void updata(int i,int l,int r,int v) { if(l==tree[i].l&&r==tree[i].r) { tree[i].num=v; return; } if(tree[i].num==v) return ; if(tree[i].num>0) { tree[i*2+1].num=tree[i*2].num=tree[i].num; tree[i].num=0; } int mid=(tree[i].l+tree[i].r)/2; if(r<=mid) { updata(i*2,l,r,v); } else if(l>mid) updata(i*2+1,l,r,v); else { updata(i*2,l,mid,v); updata(i*2+1,mid+1,r,v); } } void getsum(int i,int l,int r) { if(tree[i].num>0) { ans+=(tree[i].r-tree[i].l+1)*tree[i].num; //注意,要加1 return ; } else { int mid=(tree[i].l+tree[i].r)/2; if(r<=mid) getsum(i*2,l,r); else if(l>mid) getsum(i*2+1,l,r); else { getsum(i*2,l,mid); getsum(i*2+1,mid+1,r); } } } int main() { int t,k=0;; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); int m; scanf("%d",&m); build(1,1,n); while(m--) { int x,y,z; scanf("%d%d%d",&x,&y,&z); updata(1,x,y,z); } ans=0; getsum(1,1,n); printf("Case %d: The total value of the hook is %d.\n",++k,ans); } return 0; }
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。