洛谷 1558 色板游戏

【题解】

  容易想到用线段树维护,但是无脑开T棵线段树会导致时间超限。怎么办呢?我们可以把一个区间的状态用30位2进制数表示。第$i$位为$1$表示这个区间有第$i$种颜色,为$0$表示没有。

  这样我们只需要维护区间或的结果,并支持区间设为一个数即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define ls (u<<1)
 4 #define rs (u<<1|1)
 5 #define mid ((a[u].l+a[u].r)>>1)
 6 using namespace std;
 7 int n,m,c,l,r,col,exp[100];
 8 struct tree{
 9     int l,r,sum,same;
10 }a[400010];
11 inline int read(){
12     int k=0,f=1; char c=getchar();
13     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
14     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
15     return k*f;
16 }
17 void build(int u,int l,int r){
18     a[u].l=l; a[u].r=r; a[u].sum=1; a[u].same=0;
19     if(l<r) build(ls,l,mid),build(rs,mid+1,r);
20 }
21 void pushup(int u){a[u].sum=a[ls].sum|a[rs].sum;}
22 void pushdown(int u){
23     if(!a[u].same) return; a[u].same=0;
24     a[ls].same=a[rs].same=1;
25     a[ls].sum=a[rs].sum=a[u].sum;
26 }
27 void setsame(int u,int l,int r,int c){
28     if(l<=a[u].l&&a[u].r<=r){
29         a[u].same=1; a[u].sum=exp[c]; return;
30     }
31     pushdown(u);
32     if(l<=mid) setsame(ls,l,r,c);
33     if(r>mid) setsame(rs,l,r,c);
34     pushup(u);
35 }
36 int query(int u,int l,int r){
37     if(l<=a[u].l&&a[u].r<=r) return a[u].sum;
38     pushdown(u); int ret=0;
39     if(l<=mid) ret=query(ls,l,r);
40     if(r>mid) ret=ret|query(rs,l,r);
41     return ret;
42 }
43 int main(){
44     n=read(); c=read(); m=read(); build(1,1,n);
45     exp[1]=1;
46     for(int i=2;i<=c;i++) exp[i]=exp[i-1]<<1;
47     //for(int i=1;i<=c;i++) printf("%d ",exp[i]); puts("");
48     while(m--){
49         char ch=getchar();
50         while(ch!='P'&&ch!='C') ch=getchar();
51         if(ch=='C'){
52             l=read(); r=read(); col=read();
53             if(l>r) swap(l,r);
54             setsame(1,l,r,col);
55         }
56         else{
57             l=read(); r=read();
58             if(l>r) swap(l,r);
59             int ans=0,tmp=query(1,l,r);
60             //printf("tmp=%d ",tmp);
61             for(int i=c;i>=1;i--) if(tmp>=exp[i]) ans++,tmp-=exp[i];
62             printf("%d\n",ans);
63         }
64     }
65     return 0;
66 }
View Code

 

posted @ 2018-01-22 13:45  Driver_Lao  阅读(155)  评论(0编辑  收藏  举报