P1558 色板游戏
时间限制: 1.00s 内存限制: 128.00MB
复制 Markdown
中文
退出 IDE 模式
题目背景
阿宝上学了,今天老师拿来了一块很长的涂色板。
题目描述
色板长度为 L,L 是一个正整数,所以我们可以均匀地将它划分成 L 块 1 厘米长的小方格。并从左到右标记为 1,2,...,L。
现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:
C A B C指在 A 到 B 号方格中涂上颜色 C。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 C 或 P 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;
}