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;
}
相关推荐
那个村的李富贵11 小时前
CANN加速下的AIGC“即时翻译”:AI语音克隆与实时变声实战
人工智能·算法·aigc·cann
power 雀儿11 小时前
Scaled Dot-Product Attention 分数计算 C++
算法
琹箐12 小时前
最大堆和最小堆 实现思路
java·开发语言·算法
renhongxia112 小时前
如何基于知识图谱进行故障原因、事故原因推理,需要用到哪些算法
人工智能·深度学习·算法·机器学习·自然语言处理·transformer·知识图谱
坚持就完事了12 小时前
数据结构之树(Java实现)
java·算法
算法备案代理12 小时前
大模型备案与算法备案,企业该如何选择?
人工智能·算法·大模型·算法备案
赛姐在努力.13 小时前
【拓扑排序】-- 算法原理讲解,及实现拓扑排序,附赠热门例题
java·算法·图论
野犬寒鸦14 小时前
从零起步学习并发编程 || 第六章:ReentrantLock与synchronized 的辨析及运用
java·服务器·数据库·后端·学习·算法
霖霖总总14 小时前
[小技巧66]当自增主键耗尽:MySQL 主键溢出问题深度解析与雪花算法替代方案
mysql·算法
rainbow688914 小时前
深入解析C++STL:map与set底层奥秘
java·数据结构·算法