poj 2777

首先数字最多只有 30 种,很容易想到状压,用一个 int 来表示一个区间数字出现的状态。

很容易想到用线段树来维护一个区间数字出现的状态。

#include"cstdio"
#include"cctype"
#include"algorithm"
using namespace std;
#define lc o*2
#define rc o*2+1
#define mid (l+r)/2
int read()
{
    int c,x=0; while(!isdigit(c=getchar()));
    while(x=x*10+c-'0',isdigit(c=getchar()));
    return x;
}
int f[400001],c[400001];
void update(int o)
{
    if(c[o]) f[o]=(1<<c[o]-1); else f[o]=f[lc]|f[rc];
}
void push(int o)
{
    if(c[o]) c[lc]=c[o],c[rc]=c[o],c[o]=0;
    update(lc);
    update(rc);
}
void change(int o,int l,int r,int L,int R,int v)
{
    if(l>R || r<L) return;
    if(l>=L && r<=R)
    {
        c[o]=v;
        update(o);
        return;
    }
    push(o);
    change(lc,l,mid,L,R,v);
    change(rc,mid+1,r,L,R,v);
    update(o);
}
int query(int o,int l,int r,int L,int R)
{
    if(l>R || r<L) return 0;
    if(l>=L && r<=R) return f[o];
    push(o);
    return query(lc,l,mid,L,R)|query(rc,mid+1,r,L,R);
}
int calc(int k)
{
    int res=0;
    for(;k;k>>=1) if(k&1) res++;
    return res;
}
int main()
{
    c[1]=f[1]=1;
    int L=read(),T=read(),O=read();
    while(O--)
    {
        char c; while(c=getchar(),c!='P' && c!='C');
        if(c=='C')
        {
            int A=read(),B=read(),C=read();
            if(A>B) swap(A,B);
            change(1,1,L,A,B,C);
        }
        else
        {
            int A=read(),B=read();
            if(A>B) swap(A,B);
            printf("%d\n",calc(query(1,1,L,A,B)));
        }
    }
    return 0;
}

 

posted @ 2018-02-26 14:03  312432424  阅读(103)  评论(0编辑  收藏  举报