P1558 色板游戏 线段树+二进制状压
好,这个想法是我想拿去做HH的项链的。但是那个颜色有十万种。。。直接爆。
做这个倒是so easy
被两个地方坑了。1,a,b可能大小相反。
2,ask之前要down一波,我没down就挂了。。。。。。
注意要把+换成 |
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 struct Node 6 { 7 int l,r,sum=0,tag=0; 8 }node[400010]; 9 10 void build(int l,int r,int o) 11 { 12 node[o].l=l; 13 node[o].r=r; 14 node[o].sum=2; 15 if(l==r) return; 16 int mid=(l+r)>>1; 17 build(l,mid,o<<1); 18 build(mid+1,r,o<<1|1); 19 return; 20 } 21 void down(int o) 22 { 23 if(node[o].tag) 24 { 25 node[o<<1].tag =node[o].tag; 26 node[o<<1|1].tag=node[o].tag; 27 node[o<<1].sum =node[o].tag; 28 node[o<<1|1].sum=node[o].tag; 29 node[o].tag=0; 30 } 31 return; 32 } 33 void add(int L,int R,int v,int o) 34 { 35 if(L<=node[o].l && node[o].r<=R) 36 { 37 node[o].sum=v; 38 node[o].tag=v; 39 return; 40 } 41 if(node[o].r<L || R<node[o].l) return; 42 int mid=(node[o].l+node[o].r)>>1; 43 down(o); 44 if(L<=mid) add(L,R,v,o<<1); 45 if(mid<R) add(L,R,v,o<<1|1); 46 node[o].sum=node[o<<1].sum|node[o<<1|1].sum; 47 return; 48 } 49 int ask(int L,int R,int o) 50 { 51 if(L<=node[o].l && node[o].r<=R) return node[o].sum; 52 if(node[o].r<L || R<node[o].l) return 0; 53 down(o); 54 return ask(L,R,o<<1)|ask(L,R,o<<1|1); 55 } 56 int main() 57 { 58 int n,m,T,x,y,z; 59 char flag; 60 scanf ("%d%d%d",&n,&T,&m); 61 build(1,n,1); 62 while(m--) 63 { 64 cin>>flag; 65 if(flag=='C') 66 { 67 scanf("%d%d%d",&x,&y,&z); 68 if(x>y) swap(x,y); 69 add(x,y,(1<<z),1); 70 } 71 else 72 { 73 scanf("%d%d",&x,&y); 74 if(x>y) swap(x,y); 75 int k=ask(x,y,1),ans=0; 76 while(k) 77 { 78 ans+=(k%2); 79 k=k>>1; 80 } 81 printf("%d\n",ans); 82 } 83 } 84 return 0; 85 }