洛谷 P1558 色板游戏

题目背景

阿宝上学了,今天老师拿来了一块很长的涂色板。

题目描述

色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格。并从左到右标记为1, 2, … L。现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:1. “C A B C” 指在A到 B 号方格中涂上颜色 C。2. “P A B” 指老师的提问:A到 B号方格中有几种颜色。学校的颜料盒中一共有 T 种颜料。为简便起见,我们把他们标记为 1, 2, … T. 开始时色板上原有的颜色就为1号色。 面对如此复杂的问题,阿宝向你求助,你能帮助他吗?

输入输出格式

输入格式:
第一行有3个整数 L (1 <= L <= 100000), T (1 <= T <= 30) 和 O (1 <= O <= 100000). 在这里O表示事件数, 接下来 O 行, 每行以 “C A B C” 或 “P A B” 得形式表示所要做的事情(这里 A, B, C 为整数, 可能A> B)

输出格式:
对于老师的提问,做出相应的回答。每行一个整数。

输入输出样例

输入样例#1:
2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2
输出样例#1:
2
1

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<vector>
using namespace std;
struct Node{
    int l,r,col[31],sum,lazy_change;
    Node *son[2];
}*root;
int L,T,O;
void UpDate(Node *cur){
    for(int i=1;i<=T;i++){
        cur->col[i] = cur->son[0]->col[i] +
                            cur->son[1]->col[i];
        if(cur->col[i]) cur->sum++;
     }
    return;
}
void Built(Node *&cur,int l,int r){
    cur = new Node;
    cur->l=l; cur->r=r;
    cur->sum=0; cur->lazy_change=0;
    for(int i=1;i<=T;i++) cur->col[i] = 0;
    if(l==r){
        cur->col[1]=1;cur->sum=1;
        return;
    }
    int mid=(l+r)>>1;
    Built(cur->son[0],l,mid);
    Built(cur->son[1],mid+1,r);
    UpDate(cur);
    return;
}
void Down(Node* cur){
    for(int i=1;i<=T;i++) 
        cur->son[0]->col[i] = cur->son[1]->col[i] =0;
    cur->son[0]->col[ cur->lazy_change ] 
            = cur->son[1]->col[ cur->lazy_change ] = 1;
    cur->son[1]->lazy_change = 
        cur->son[0]->lazy_change = cur->lazy_change;
    cur->son[1]->sum = cur->son[0]->sum = 1;
    cur->lazy_change=0;
}
void Change(Node* cur,int l,int r,int x){
    if(l == cur->l&&cur->r ==r){
        cur->sum=1;
        for(int i=1;i<=T;i++) cur->col[i]=0;
        cur->col[x]=1;cur->lazy_change=x;
        return ;
    }
    if(cur->lazy_change) Down(cur);
    int mid=(cur->l + cur->r)>>1;
    if(l>mid) Change(cur->son[1],l,r,x);
    else if(r<=mid) Change(cur->son[0],l,r,x);
    else Change(cur->son[0],l,mid,x),
            Change(cur->son[1],mid+1,r,x);
    UpDate(cur);
}
int flag[35];
void Query(Node* cur,int l,int r){
    if(l == cur->l && cur->r == r){
        for(int i=1;i<=T;i++) flag[i] += cur->col[i];
        return ;
    }
    if(cur->lazy_change) Down(cur);
    int mid=(cur->l + cur->r) >>1;
    if(l>mid)  Query(cur->son[1],l,r);
    else if(r<=mid)  Query(cur->son[0],l,r);
    else Query(cur->son[0],l,mid)
            ,Query(cur->son[1],mid+1,r);
    return ;
}
int solve(){
    int ans=0;
    for(int i=1;i<=T;i++) if(flag[i]) ans++;
    return ans;
}
int main(){
    scanf("%d%d%d",&L,&T,&O);
    Built(root,1,L);
    char C;
    int L,R,X;
    while(O--){
        cin>>C;
        if(C=='C'){
            scanf("%d%d%d",&L,&R,&X);
            if(L>R) swap(L,R);
            Change(root,L,R,X);
        }
        else if(C=='P'){
            scanf("%d%d",&L,&R);
            if(L>R) swap(L,R);
            memset(flag,0,sizeof flag );
            Query(root,L,R);
            printf("%d\n",solve());
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值