题目大意:
有一个长度为L的木板,在上面可以涂t种颜色,有p个操作,操作可以是将a-b涂成c的颜色,也可以是询问a-b有多少种不同的颜色,对每次询问输出答案。
#include<iostream>
#include<stdio.h>
#include<string.h>
#define maxn 100000
using namespace std;
struct TREE{
int left,right;
int color;
}t[maxn*4+10];
bool vis[40]; //记录颜色是否出现过
//建树
void buildtree(int root,int left,int right){
t[root].left=left;
t[root].right=right;
t[root].color=1; //初始化,对于底层节点表示该点的颜色为1;对于非底层节点则表示该节点对应的所有颜色均为1
if(left==right)
return;
int mid=(right+left)/2;
buildtree(root*2,left,mid);
buildtree(root*2+1,mid+1,right);
}
//更新
//t[root]==0 表示该节点对应的区间颜色不单一
//t[root]!=0 表示该节点对应的区间颜色单一,且为t[root]的值
//始终牢记线段树的更新是从根节点开始的 即从上向下更新,直到更新到想要的区间才停止更新
void update(int root,int left,int right,int color){ //更新时注意保留原始的更新区间
if(t[root].left==left&&t[root].right==right){ //如果某节点的区间刚好等于想要更新的区间
t[root].color=color; //将该点的颜色进行更新,并不再向下更新
return;
}
if(t[root].color==color) return; //如果某节点的颜色更好等于想要更新的颜色,不再向下更新(优化,不写也能过)
if(t[root].color){ //如果该区间颜色单一
t[root*2].color=t[root].color; //更新下面节点的颜色
t[root*2+1].color=t[root].color;
t[root].color=0; //该点的颜色设置为不单一
}
int mid=(t[root].left+t[root].right)/2;
if(right<=mid) update(root*2,left,right,color); //别写成update(root*2,left,mid+1,color) 这样的话是把左边的都更新了
else if(left>mid) update(root*2+1,left,right,color);
else{
update(root*2,left,mid,color); //这两个区间合并起来是left-right
update(root*2+1,mid+1,right,color);
}
}
//询问
void query(int root,int begin,int end){ //询问时注意保留原始的询问区间
if(t[root].color){ //如果该点对应的区间下为单一颜色
vis[t[root].color]=1; //标记该颜色出现过
return; //不继续向下找了
}
int mid=(t[root].left+t[root].right)/2;
if(end<=mid) query(root*2,begin,end);
else if(begin>mid) query(root*2+1,begin,end);
else{
query(root*2,begin,mid);query(root*2+1,mid+1,end);
}
}
int main(){
int l,T,p,i,j;
while(scanf("%d%d%d",&l,&T,&p)!=EOF){
buildtree(1,1,l);
for(j=1;j<=p;j++){
getchar(); //注意
char ch;
scanf("%c",&ch);
int a,b,c;
scanf("%d%d",&a,&b);
if (a>b)
swap(a,b);
if(ch=='P'){
memset(vis,0,sizeof(vis));
int sum=0;
query(1,a,b);
for(i=1;i<=T;i++)
if(vis[i]==1){
sum++;
}
printf("%d\n",sum);
}
if(ch=='C'){
scanf("%d",&c);
update(1,a,b,c);
}
}
}
return 0;
}