POJ 2777 Count Color
线段树第三题,这是优化很奇葩的题。领教了。
题目大意:
给出每一个广告牌每次的涂色区间,查找某个区间内共有多少种颜色。
解题思路:
就是线段树啊。不过需要二进制优化,因为最多不超过30种颜色,所以完全可以用一个整形变量来存某一个区间内出现的颜色的种类。如果不这样的话就超时的死死地。。。
下面是代码:
#include <stdio.h> #include <string.h> const int Max=100005; int node[Max*3],bit[Max*3],ans; bool vis[35]; void Pushdown(int tr) { if(node[tr]) { node[tr<<1]=node[tr]; node[tr<<1|1]=node[tr]; bit[tr<<1]=bit[tr]; bit[tr<<1|1]=bit[tr]; node[tr]=0; } } void Pushup(int tr) { bit[tr]=bit[tr<<1]|bit[tr<<1|1]; } void update(int a,int b,int c,int l,int r,int tr) { if(a<=l&&r<=b) { node[tr]=c; bit[tr]=1<<(c-1); return ; } Pushdown(tr); int m=(l+r)>>1; if(a<=m)update(a,b,c,l,m,tr<<1); if(m<b)update(a,b,c,m+1,r,tr<<1|1); Pushup(tr); } void query(int a,int b,int l,int r,int tr ) { if(a<=l&&r<=b) { ans|=bit[tr]; return; } if(l==r)return ; Pushdown(tr); int m=(l+r)>>1; if(a<=m) query(a,b,l,m,tr<<1); if(m<b) query(a,b,m+1,r,tr<<1|1); } int does(int x) { int cnt=0; while(x) { if(x&1)cnt++; x>>=1; } return cnt; } int main() { int l,t,o; while(scanf("%d%d%d",&l,&t,&o)!=EOF) { char s[3]; int a,b,c; update(1,l,1,1,l,1); for(int i=0;i<o;i++) { scanf("%s",s); scanf("%d%d",&a,&b); if(a>b) { int t=a; a=b; b=t; } if(s[0]=='C') { scanf("%d",&c); update(a,b,c,1,l,1); } else { memset(vis,false,sizeof(vis)); ans=0; query(a,b,1,l,1); printf("%d\n",does(ans)); } } } return 0; }