题目:http://poj.org/problem?id=2777
状压每个颜色的选择情况,取答案时 | 一番;
注意题目中的区间端点可能大小相反,在读入时换一下位置;
注意pushdown()中要lazy标签不为0才进行更新。
代码如下:
#include<iostream> #include<cstdio> using namespace std; int const N=2000005; int t[N],lazy[N],len,tt,o; char dc; void pushdown(int x) { if(lazy[x])//! { lazy[x*2]=lazy[x]; lazy[x*2+1]=lazy[x]; t[x*2]=lazy[x]; t[x*2+1]=lazy[x]; lazy[x]=0; } } void pushup(int x) { t[x]=(t[x*2]|t[x*2+1]); } void build(int l,int r,int x) { t[x]=1; if(l==r)return; int mid=(l+r)/2; build(l,mid,x*2); build(mid+1,r,x*2+1); } void update(int l,int r,int ll,int rr,int s,int x) { if(l>=ll&&r<=rr) { t[x]=s; lazy[x]=s; return; } pushdown(x); int mid=(l+r)/2; if(mid>=ll)update(l,mid,ll,rr,s,x*2); if(mid<rr)update(mid+1,r,ll,rr,s,x*2+1); pushup(x); } int query(int l,int r,int ll,int rr,int x) { int ans=0; if(l>=ll&&r<=rr) return t[x]; pushdown(x); int mid=(l+r)/2; if(mid>=ll)ans|=query(l,mid,ll,rr,x*2); if(mid<rr)ans|=query(mid+1,r,ll,rr,x*2+1); return ans; } int main() { while(scanf("%d%d%d",&len,&tt,&o)==3) { build(1,len,1); while(o--) { cin>>dc; // printf("(%c)\n",dc); if(dc=='C') { int x,y,z; scanf("%d%d%d",&x,&y,&z); if(x>y)swap(x,y); z=(1<<(z-1)); update(1,len,x,y,z,1); } if(dc=='P') { int x,y; scanf("%d%d",&x,&y); if(x>y)swap(x,y); int k=query(1,len,x,y,1); int ans=0; for(int i=1;i<=tt;i++) if(k&(1<<(i-1)))ans++; printf("%d\n",ans); } } } return 0; }