题目地址:
http://poj.org/problem?id=2777
题目概述:
给一块长度为L的板子,有两种操作,第一种将A到B刷成颜色C,第二种询问A到B一共有多少种颜色。颜色数小于等于30。
大致思路:
首先很容易发现线段树可以解决问题,不过怎么储存颜色呢?我们发现颜色总数很少,于是可以为2进制位来表示颜色,问题就可以很好地解决了。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <vector> #include <ctime> #include <map> #include <stack> #include <queue> #include <cstring> #include <algorithm> using namespace std; #define sacnf scanf #define scnaf scanf #define maxn 100010 #define maxm 26 #define inf 1061109567 #define Eps 0.00001 const double PI=acos(-1.0); #define mod 7 #define MAXNUM 10000 void Swap(int &a,int &b) {int t=a;a=b;b=t;} int Abs(int x) {return (x<0)?-x:x;} typedef long long ll; typedef unsigned int uint; struct node { int Set_flag,color; } tree[maxn*3]; int t,p2[32]; void build_tree(int l,int r,int dir) { tree[dir].color=(1<<1);tree[dir].Set_flag=0; if(l==r) return; int m=(l+r)>>1; build_tree(l,m,dir*2); build_tree(m+1,r,dir*2+1); } void pushdown(int l,int r,int dir) { if(l!=r) { tree[dir*2].Set_flag=tree[dir].Set_flag; tree[dir*2+1].Set_flag=tree[dir].Set_flag; tree[dir*2].color=tree[dir*2+1].color=(1<<tree[dir].Set_flag); } tree[dir].color=(1<<tree[dir].Set_flag); tree[dir].Set_flag=0; } void Set(int l,int r,int dir,int sl,int sr,int c) { if(sr<l||r<sl) return; if(sl<=l&&r<=sr) { tree[dir].Set_flag=c; tree[dir].color=(1<<c); return; } if(tree[dir].Set_flag!=0) pushdown(l,r,dir); int m=(l+r)>>1; Set(l,m,dir*2,sl,sr,c); Set(m+1,r,dir*2+1,sl,sr,c); tree[dir].color=(tree[dir*2].color|tree[dir*2+1].color); } int query(int l,int r,int dir,int ql,int qr) { if(qr<l||r<ql) return 0; if(tree[dir].Set_flag!=0) pushdown(l,r,dir); if(ql<=l&&r<=qr) return tree[dir].color; int m=(l+r)>>1,t1,t2; t1=query(l,m,dir*2,ql,qr); t2=query(m+1,r,dir*2+1,ql,qr); return (t1|t2); } void debug(int n) { for(int i=1;i<2*n;i++) { printf("%d ",tree[i].Set_flag); /*for(int j=1;j<=t;j++) if(tree[i].color[j]!=0) printf("%d,",j); printf(" ");*/ } printf(" "); } int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); //clock_t st=clock(); int l,o;p2[0]=1; for(int i=1;i<=30;i++) p2[i]=p2[i-1]*2; while(~scanf("%d%d%d",&l,&t,&o)) { build_tree(1,l,1); while(o--) { getchar();char c;int a,b,p; scanf("%c%d%d",&c,&a,&b); if(a>b) Swap(a,b); if(c=='C') { scanf("%d",&p); Set(1,l,1,a,b,p); } else if(c=='P') { int ans=query(1,l,1,a,b); int cnt=0; for(int i=1;i<=t;i++) if((ans&p2[i])==p2[i]) cnt++; printf("%d ",cnt); } //debug(l); } } //clock_t ed=clock(); //printf(" Time Used : %.5lf Ms. ",(double)(ed-st)/CLOCKS_PER_SEC); return 0; }