这个题目我想说一些。由于数据量比较大,如果每次建树,更新叶子节点,时间的开销是相当大的,超时是必然的。这个题目是成段更新区间。如果非叶子节点所在的区间的颜色不止一种的时候,这个基点赋值一个不可能的颜色值,就赋值为-1了。如果某个区间的颜色单一,就赋值为这个颜色的值。这样有助于区间的成段更新。还有就是用一个bool数组visited来标记某个区间的颜色的数目,因为颜色最多也就30种。每一个下标表示一个特定的颜色。这样访问这个bool数组就可以知道这个区间中有多少种颜色了。
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 100002
struct SegTree
{
int l,r,mid;
int color;
}tree[N*3];
bool visited[32];
void BuildTree(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
tree[root].color=1;
tree[root].mid=(l+r)/2;
if(l==r)return;
BuildTree(2*root,l,tree[root].mid);
BuildTree(2*root+1,tree[root].mid+1,r);
}
void Updata(int root,int a,int b,int c)
{
if(tree[root].l==a&&tree[root].r==b) //三个if表明区间在成段更新
{
tree[root].color=c;
return ;
}
if(tree[root].color==c)return;
if(tree[root].color!=-1)
{
tree[2*root].color=tree[root].color;
tree[2*root+1].color=tree[root].color;
tree[root].color=-1;
}
if(b<=tree[root].mid)
{
Updata(2*root,a,b,c);
}
else if(a>tree[root].mid)
{
Updata(2*root+1,a,b,c);
}
else
{
Updata(2*root,a,tree[root].mid,c);
Updata(2*root+1,tree[root].mid+1,b,c);
}
}
void Query(int root,int a,int b)
{
if(tree[root].color!=-1) //最多也就涂30种色,每一个值代表一种颜色
{
visited[tree[root].color]=true;
return ;
}
if(b<=tree[root].mid)
{
Query(2*root,a,b);
}
else if(a>tree[root].mid)
{
Query(2*root+1,a,b);
}
else
{
Query(2*root,a,tree[root].mid);
Query(2*root+1,tree[root].mid+1,b);
}
}
int main()
{
int L,T,oper;
while(scanf("%d%d%d",&L,&T,&oper)!=EOF)
{
BuildTree(1,1,L);
while(oper--)
{
char ch[3];
int a,b;
scanf("%s%d%d",ch,&a,&b);
if(a>b)
{
int temp=a;
a=b;
b=temp;
}
if(ch[0]=='P')
{
int count=0;
memset(visited,false,sizeof(visited));
Query(1,a,b);
for(int i=1;i<=30;i++)
{
if(visited[i])count++;
}
printf("%d\n",count);
}
else
{
int c;
scanf("%d",&c);
Updata(1,a,b,c);
}
}
}
return 0;
}