P1558 色板游戏 [线段树 + 二进制状态压缩 + 懒标记区间重置]

P1558 色板游戏

时间限制: 1.00s 内存限制: 128.00MB

复制 Markdown

中文

退出 IDE 模式

题目背景

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

题目描述

色板长度为 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≤105),T(1≤T≤30) 和 O(1≤O≤105)。 在这里 O 表示事件数。

接下来 O 行, 每行以 C A B CP A B 的形式表示所要做的事情(这里 A,B,C 为整数,可能 A>B,这样的话需要你交换 A 和 B)。

输出格式

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

输入输出样例

输入 #1复制运行

复制代码
2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2

输出 #1复制运行

复制代码
2
1

说明/提示

【数据范围】

1≤L≤105,1≤T≤30,1≤O≤105。

1≤A,B≤L(不保证 A≤B),1≤C≤T。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long 
const int N=1e5+5;
int a[N],n,m,t;
struct SegmentTree{
    int l,r,sum,upd;
    bool isupd;
    #define l(x) tree[x].l
    #define r(x) tree[x].r
    #define sum(x) tree[x].sum
    #define upd(x) tree[x].upd
    #define isupd(x) tree[x].isupd
}tree[N<<2];
void pushup(int p){
    sum(p)=sum(p<<1)|sum(p<<1|1);
}
void build(int p,int l,int r){
    l(p)=l,r(p)=r;
    if(l(p)==r(p)){
        sum(p)=1;return; 
    }
    int mid =(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    pushup(p);
}
void pushdown(int p){
    if(isupd(p)){
        upd(p<<1)=upd(p<<1|1)=upd(p);
        isupd(p<<1)=isupd(p<<1|1)=1;
        sum(p<<1)=sum(p<<1|1)=1<<(upd(p)-1);
        isupd(p)=0;
    }
}
void change(int p,int l,int r,int k){
    if(l<=l(p)&&r>=r(p)){
        upd(p)=k;
        sum(p)=1<<(upd(p)-1);
        isupd(p)=1;
        return;
    }
    pushdown(p);
    int mid=(l(p)+r(p))>>1;
    if(l<=mid)change(p<<1,l,r,k);
    if(r>mid)change(p<<1|1,l,r,k);
    pushup(p);
}
int query(int p,int l,int r){
    if(l<=l(p)&&r>=r(p)){return sum(p);}
    pushdown(p);
    int mid=(l(p)+r(p))>>1;
    int val=0;
    if(l<=mid)val|=query(p<<1,l,r);
    if(r>mid)val|=query(p<<1|1,l,r);
    return val;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>t>>m;
    for(int i=1;i<=n;i++)a[i]=1;
    build(1,1,n);
    while(m--){
        int l,r;
        char op;
        cin>>op>>l>>r;
        if(l>r)swap(l,r);
        if(op=='C'){
            int k;cin>>k;
            change(1,l,r,k);
        }else {
            cout<<__builtin_popcountll(query(1,l,r))<<'\n';
        }
    }
    return 0;
}
相关推荐
-dzk-2 小时前
【代码随想录】LC 59.螺旋矩阵 II
c++·线性代数·算法·矩阵·模拟
风筝在晴天搁浅2 小时前
hot100 78.子集
java·算法
Jasmine_llq2 小时前
《P4587 [FJOI2016] 神秘数》
算法·倍增思想·稀疏表(st 表)·前缀和数组(解决静态区间和查询·st表核心实现高效预处理和查询·预处理优化(提前计算所需信息·快速io提升大规模数据读写效率
超级大只老咪3 小时前
快速进制转换
笔记·算法
m0_706653233 小时前
C++编译期数组操作
开发语言·c++·算法
故事和你913 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
qq_423233903 小时前
C++与Python混合编程实战
开发语言·c++·算法
TracyCoder1233 小时前
LeetCode Hot100(19/100)——206. 反转链表
算法·leetcode
m0_715575343 小时前
分布式任务调度系统
开发语言·c++·算法