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;
}


posted @ 2014-02-20 19:41  、小呆  阅读(117)  评论(0编辑  收藏  举报