题目背景
阿宝上学了,今天老师拿来了一块很长的涂色板。
题目描述
色板长度为(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 leq L leq 100000)), (T (1 leq T leq 30)) 和 (O (1 leq O leq 100000))。 在这里(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
思路:正解貌似是基于二进制来建线段树,但是我不会……于是我就非常暴力的建了(t)棵线段树,因为(t)只有(30)嘛,所以建(30)棵线段树也不会爆,没棵线段树代表一个颜色,然后对于每一个(C)操作,就是修改要修改的那个颜色的对应线段树的对应修改区间为(1),其余线段树的对应修改区间修改为(0),然后查询就是把每棵线段树的区间颜色数加起来。但是代码可能因为常数优化的不太好等原因,不开(O(2))会(TLE)一个点。
代码:
#include<cstdio>
#include<algorithm>
#define maxn 100007
#define ls rt<<1
#define rs rt<<1|1
#define re register
using namespace std;
int n,t,m,sum[31][maxn<<2],lazy[31][maxn<<2];
char s[2];
inline void pushup(int i, int rt) {
sum[i][rt]=sum[i][ls]+sum[i][rs];
}
inline void pushdown(int i, int rt) {
if(lazy[i][rt]==-1) {
sum[i][ls]=sum[i][rs]=0;
lazy[i][ls]=lazy[i][rs]=-1;
}
else {
lazy[i][ls]=lazy[i][rs]=lazy[i][rt];
sum[i][ls]=sum[i][rs]=lazy[i][rt];
}
lazy[i][rt]=0;
}
void build(int rt, int l, int r) {
if(l==r) {
sum[1][rt]=1;
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(1,rt);
}
void modify(int i, int rt, int l, int r, int L, int R, int val) {
if(L>r||R<l) return;
if(L<=l&&r<=R) {
sum[i][rt]=val;
if(!val) lazy[i][rt]=-1;
else lazy[i][rt]=val;
return;
}
if(lazy[i][rt]) pushdown(i,rt);
int mid=(l+r)>>1;
if(L<=mid) modify(i,ls,l,mid,L,R,val);
if(R>mid) modify(i,rs,mid+1,r,L,R,val);
pushup(i,rt);
}
int csum(int i, int rt, int l, int r, int L, int R) {
if(L>r||R<l) return 0;
if(L<=l&&r<=R) return sum[i][rt];
if(lazy[i][rt]) pushdown(i,rt);
int mid=(l+r)>>1;
return csum(i,ls,l,mid,L,R)+csum(i,rs,mid+1,r,L,R);
}
int main() {
scanf("%d%d%d",&n,&t,&m);
build(1,1,n);
for(re int i=1,l,r,v;i<=m;++i) {
scanf("%s%d%d",s,&l,&r);
if(l>r) swap(l,r);
if(s[0]=='C') {
scanf("%d",&v);
for(re int k=1;k<=t;++k) {
if(k!=v) modify(k,1,1,n,l,r,0);
else modify(k,1,1,n,l,r,1);
}
}
else {
int zrj=0;
for(re int k=1;k<=t;++k)
if(csum(k,1,1,n,l,r)) zrj++;
printf("%d
",zrj);
}
}
return 0;
}