题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698
题目的题意就是:给你一些牌子(铜,银,金)分别用1,2,3表示,一开始这些都是铜牌。现在对这些区间区间进行操作,比如说将1到5的牌子涂成银牌等等。最后统计这些牌子的总价值。
用到了懒人标记法
#include <iostream> #include <cstdio> #include <cstdlib> #define M 100010 using namespace std; int n; struct TREE { int l,r,v,c;//左节点,右节点,区间价值,何种颜色 bool p;//是否为单一颜色 }T[M<<2]; void create(int u,int l,int r) { T[u].l=l;T[u].r=r;T[u].p=1; if(l==r) { T[u].v=1; T[u].c=1; return; } int mid=(T[u].l+T[u].r)>>1; create(u<<1,l,mid); create(u<<1|1,mid+1,r); if(T[u<<1].p&&T[u<<1|1].p) {T[u].p=1;T[u].c=T[u<<1].c;} else {T[u].p=0;T[u].c=0;} T[u].v=T[u<<1].v+T[u<<1|1].v; } void updata(int u,int l,int r,int c) { if(T[u].l>=l&&T[u].r<=r) { T[u].p=1;T[u].c=c;T[u].v=c*(T[u].r-T[u].l+1); return; } int mid=(T[u].l+T[u].r)>>1; if(r<=mid) { if(T[u].p) { T[u<<1|1].p=T[u<<1].p=1; T[u<<1].v=T[u].c*(T[u<<1].r-T[u<<1].l+1); T[u<<1|1].v=T[u].v-T[u<<1].v; T[u<<1|1].c=T[u<<1].c=T[u].c; T[u].p=0;T[u].c=0; updata(u<<1,l,r,c); } else updata(u<<1,l,r,c); } else if(l>=mid+1) { if(T[u].p) { T[u<<1|1].p=T[u<<1].p=1; T[u<<1].v=T[u].c*(T[u<<1].r-T[u<<1].l+1); T[u<<1|1].v=T[u].v-T[u<<1].v; T[u<<1|1].c=T[u<<1].c=T[u].c; T[u].p=0;T[u].c=0; updata(u<<1|1,l,r,c); } else updata(u<<1|1,l,r,c); } else { if(T[u].p) { T[u<<1|1].p=T[u<<1].p=1; T[u<<1].v=T[u].c*(T[u<<1].r-T[u<<1].l+1); T[u<<1|1].v=T[u].v-T[u<<1].v; T[u<<1|1].c=T[u<<1].c=T[u].c; T[u].p=0;T[u].c=0; updata(u<<1,l,r,c); updata(u<<1|1,l,r,c); } else { updata(u<<1,l,r,c); updata(u<<1|1,l,r,c); } } T[u].v=T[u<<1].v+T[u<<1|1].v; } int main() { int t,m,a,b,c; scanf("%d",&t); for(int i=1;i<=t;i++) { scanf("%d",&n); create(1,1,n); scanf("%d",&m); for(int j=1;j<=m;j++) { scanf("%d%d%d",&a,&b,&c); updata(1,a,b,c); } printf("Case %d: The total value of the hook is %d.\n",i,T[1].v); } //system("pause"); return 0; }