Luogu P1558 色板遊戲【線段樹/狀態壓縮】By cellur925
阿新 • • 發佈:2018-11-03
今天非常想再看一遍霸王別姬想不進去題於是開始刷資料結構
注意到至多隻有\(30\)種顏色,啊啊啊啊我一開始竟然想的不是狀態壓縮而是線上段樹中存一個30大小的陣列,這樣每次更新的時候暴力迴圈一遍。hhhhh。
可能這樣比較好想吧,但是比正解狀態壓縮一下不知道差到哪裡去了:)。開始還智障地把每次迴圈的次數開成30,那給出的色板數有什麼用hh,這樣是80分,改後AC。
#include<cstdio> #include<algorithm> #define maxn 100090 using namespace std; int n,Q,tot; char op[10]; struct SegmentTree{ int l,r;int lazy; int col[35]; }t[maxn*4]; void re(int &x) { x=0; char ch=getchar(); bool flag=false; while(ch<'0'||ch>'9') flag|=(ch=='-'),ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); x=flag ? -x : x; } void build(int p,int l,int r) { t[p].l=l,t[p].r=r; if(l==r) { t[p].col[1]=1; return ; } int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); t[p].col[1]=t[p<<1].col[1]+t[p<<1|1].col[1]; } void update(int p) { if(!t[p].lazy||t[p].l==t[p].r) return ; t[p<<1].lazy=t[p].lazy;t[p<<1|1].lazy=t[p].lazy; for(int i=1;i<=tot;i++) t[p<<1].col[i]=0,t[p<<1|1].col[i]=0; t[p<<1].col[t[p].lazy]+=t[p<<1].r-t[p<<1].l+1; t[p<<1|1].col[t[p].lazy]+=t[p<<1|1].r-t[p<<1|1].l+1; t[p].lazy=0; } void change(int p,int l,int r,int id) { update(p); if(t[p].l==l&&t[p].r==r) { for(int i=1;i<=tot;i++) t[p].col[i]=0; t[p].col[id]+=r-l+1; t[p].lazy=id; return ; } int mid=(t[p].l+t[p].r)>>1; if(l>mid) change(p<<1|1,l,r,id); else if(r<=mid) change(p<<1,l,r,id); else change(p<<1,l,mid,id),change(p<<1|1,mid+1,r,id); for(int i=1;i<=tot;i++) t[p].col[i]=t[p<<1].col[i]+t[p<<1|1].col[i]; } int ask(int p,int l,int r,int id) { update(p); if(t[p].l==l&&t[p].r==r) return t[p].col[id]; int mid=(t[p].l+t[p].r)>>1; if(l>mid) return ask(p<<1|1,l,r,id); else if(r<=mid) return ask(p<<1,l,r,id); else return ask(p<<1,l,mid,id)+ask(p<<1|1,mid+1,r,id); } int main() { scanf("%d%d%d",&n,&tot,&Q); build(1,1,n); while(Q--) { scanf("%s",op+1); if(op[1]=='C') { int x=0,y=0,z=0; scanf("%d%d%d",&x,&y,&z); if(x>y) swap(x,y); change(1,x,y,z); } else if(op[1]=='P') { int x=0,y=0; scanf("%d%d",&x,&y); if(x>y) swap(x,y); int cnt=0; for(int i=1;i<=tot;i++) if(ask(1,x,y,i)>0) cnt++; printf("%d\n",cnt); } } return 0; }
最正確的做法是把每個節點的色板情況壓成一個狀態數,更新的時候用位運算更新==。這種方法我沒有寫,找了一個大佬寫的:傳送門