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;
}
相关推荐
漫随流水13 小时前
leetcode算法(515.在每个树行中找最大值)
数据结构·算法·leetcode·二叉树
mit6.82414 小时前
dfs|前后缀分解
算法
扫地的小何尚14 小时前
NVIDIA RTX PC开源AI工具升级:加速LLM和扩散模型的性能革命
人工智能·python·算法·开源·nvidia·1024程序员节
千金裘换酒15 小时前
LeetCode反转链表
算法·leetcode·链表
byzh_rc16 小时前
[认知计算] 专栏总结
线性代数·算法·matlab·信号处理
qq_4335545416 小时前
C++ manacher(求解回文串问题)
开发语言·c++·算法
歌_顿16 小时前
知识蒸馏学习总结
人工智能·算法
闲看云起17 小时前
LeetCode-day6:接雨水
算法·leetcode·职场和发展
没学上了17 小时前
VLM_一维离散卷积与二维离散卷积(还是复习感觉还行)
算法