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;
}
相关推荐
wuweijianlove1 小时前
算法性能的渐近与非渐近行为对比的技术4
算法
_dindong2 小时前
cf1091div2 C.Grid Covering(数论)
c++·算法
AI成长日志2 小时前
【Agentic RL】1.1 什么是Agentic RL:从传统RL到智能体学习
人工智能·学习·算法
黎阳之光2 小时前
黎阳之光:视频孪生领跑者,铸就中国数字科技全球竞争力
大数据·人工智能·算法·安全·数字孪生
skywalker_112 小时前
力扣hot100-3(最长连续序列),4(移动零)
数据结构·算法·leetcode
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 17. 电话号码的字母组合 | C++ 回溯算法经典模板
c++·算法·leetcode
wfbcg3 小时前
每日算法练习:LeetCode 209. 长度最小的子数组 ✅
算法·leetcode·职场和发展
_日拱一卒3 小时前
LeetCode:除了自身以外数组的乘积
数据结构·算法·leetcode
计算机安禾3 小时前
【数据结构与算法】第36篇:排序大总结:稳定性、时间复杂度与适用场景
c语言·数据结构·c++·算法·链表·线性回归·visual studio
SatVision炼金士3 小时前
合成孔径雷达干涉测量(InSAR)沉降监测算法体系
算法