P1558 色板游戏 (线段树)

题目链接


Solution

一个简单的 或 线段树.竟然坑了我一个小时...
因为颜色很小,所以把状态压起来.
然后每个节点上的数值代表当前颜色状态.
然后节点合并很简单,直接或起来.
需要注意一下的地方是修改时的 \(lazy\) ,要完全覆盖,这里不能或.

Code

#include<bits/stdc++.h>
#define ll long long
#define in(x) x=read()
#define mid (l+r)/2
#define N 100001
using namespace std;
ll sgm[N*4],lazy[N*4],n,m,t;

int read()
{
    char ch=getchar(); int f=1,w=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
    return f*w;
}

void build(int node,int l,int r)
{
	sgm[node]=1; if(l==r)return;
    build(node*2,l,mid),build(node*2+1,mid+1,r);
}

void push_down(int node)
{
    if(!lazy[node])return;
    lazy[node*2]=lazy[node*2+1]=lazy[node];
    sgm[node*2]=sgm[node*2+1]=lazy[node]; lazy[node]=0;
}

void change(int node,int l,int r,int L,int R,int v)
{
    if(l>R||r<L)return;
    if(l>=L&&r<=R){
        sgm[node]=lazy[node]=(1<<v-1);
        return;
    }
    push_down(node);
    change(node*2,l,mid,L,R,v);
    change(node*2+1,mid+1,r,L,R,v);
    sgm[node]=sgm[node*2]|sgm[node*2+1];
}

ll query(int node,int l,int r,int L,int R)
{
    if(l>R||r<L)return 0;
    if(l>=L&&r<=R)return sgm[node];
    push_down(node);
    return query(node*2,l,mid,L,R)|query(node*2+1,mid+1,r,L,R);
}

int main()
{
    in(n),in(t),in(m);
    build(1,1,n);
    while(m--)
    {
        char opt; int l,r,v;
        cin>>opt; 
        if(opt=='C')
        {
            in(l),in(r),in(v);
            if(l>r)swap(l,r);
            change(1,1,n,l,r,v);
        }
        else
        {
            in(l),in(r); int ans=0;
            if(l>r)swap(l,r);
            ll pp=query(1,1,n,l,r);
            for(int i=0;i<=t;i++)
            if(pp&(1<<i))ans++;
            
            printf("%d\n",ans);
        }
    }
}
posted @ 2018-10-11 22:01  Kevin_naticl  阅读(313)  评论(0编辑  收藏  举报