洛谷 P1558 色板游戏

传送门:洛谷 P1558 色板游戏
算法分析:观察到数据范围:\(1\leq T\leq 30\) ,考虑使用二进制来进行状态压缩
将颜色\(x\)表示为 \(1<<(x-1)\)\(2^{x-1}\),使用线段树动态维护即可


#include<iostream>
#include<cstdio>
#define maxN 100010
#define ls k<<1
#define rs k<<1 | 1
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
ll sum[maxN*4+1],v[maxN*4+1];
int n,m,x,y,z,T;
char op[3];
void pushdown(int,int,int),pushup(int);
ll query(int,int,int,int,int);
void update(int,int,int,int,int,int);
void print(ll);
void build(int,int,int);
int main()
{
    scanf("%d%d%d",&n,&T,&m);
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        scanf("%s%d%d",op,&x,&y);
        if(op[0]=='C')
        {
            scanf("%d",&z);
            update(1,1,n,min(x,y),max(x,y),1<<(z-1));
        }
        else print(query(1,1,n,min(x,y),max(x,y)));
    }
    return 0;
}
void build(int k,int l,int r)
{
    if(l==r) {sum[k]=1; return;}
    build(ls,l,mid); build(rs,mid+1,r);
    pushup(k);
}
void print(ll x)
{
    int sum=0;
    while(x) {sum+=(x&1); x>>=1;}
    printf("%d\n",sum);
}
void pushup(int k) {sum[k]=sum[ls]|sum[rs];}
void pushdown(int k,int l,int r)
{
    v[ls]=v[rs]=sum[ls]=sum[rs]=v[k];
    v[k]=0;
}
void update(int k,int l,int r,int ql,int qr,int u)
{
    if(ql<=l && r<=qr)
    {
        sum[k]=u;
        v[k]=u; return;
    }
    if(v[k]) pushdown(k,l,r);
    if(ql<=mid) update(ls,l,mid,ql,qr,u);
    if(qr>mid) update(rs,mid+1,r,ql,qr,u);
    pushup(k);
}
long long query(int k,int l,int r,int ql,int qr)
{
    if(ql<=l && r<=qr) return sum[k];
    long long ans=0;
    if(v[k]) pushdown(k,l,r);
    if(ql<=mid) ans|=query(ls,l,mid,ql,qr);
    if(qr>mid) ans|=query(rs,mid+1,r,ql,qr);
    return ans;
}
posted @ 2019-02-10 15:48  常青藤的花语  阅读(137)  评论(0编辑  收藏  举报

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。