统计一定区间内颜色的不同种数
开个hash,在search随时记录颜色数目
做完这题:
对线段树有了理解
更新操作时,线段树用遗传的方法,在一个区间异化时,将有用信息遗传到子代(仅仅是子代,不是所有的子孙都遗传,这样就节约了时间)
统计操作时,线段树用了区间统计(不是统计每个叶子),统计未被异化的区间(不是所有子孙都统计,又节约时间了)
对于函数参数的理解:
当传入的是结点下标n时,函数里考虑n+n,n+n+1的子树
而不仅传入有下标,还有区间时,就要分区间是在当前树的左子树,或是右子树,或是区间同时在左右子树

#include<stdio.h>
struct data
{
int l,r,val;
}node[300009];
bool hash[39];
inline int max(int a,int b)
{
return a>b?a:b;
}
void build(int ll,int rr,int n)
{
node[n].l=ll;
node[n].r=rr;
node[n].val=1;
if (ll==rr) return ;
int mid=(ll+rr)/2;
build(ll,mid,2*n);
build(mid+1,rr,2*n+1);
}
void updata(int ll,int rr,int a,int n)
{
if(node[n].val==a)return ;
if (node[n].l==ll&&node[n].r==rr)
{
node[n].val=a;
return ;
}
if(node[n].val!=-1)
{
node[n+n].val=node[n].val;
node[n+n+1].val=node[n].val;
node[n].val=-1;
}
int mid=(node[n].l+node[n].r)/2;
if (rr<=mid) updata(ll,rr,a,2*n);
else if (ll>=mid+1) updata(ll,rr,a,2*n+1);
else
{
updata(ll,mid,a,2*n);
updata(mid+1,rr,a,2*n+1);
}
}
void search(int ll,int rr,int n)
{
if(node[n].l<=ll&&node[n].r>=rr&&node[n].val!=-1)//所问区间在 已知结点的范围内,标记后,返回
{
hash[node[n].val]=1;
return;
}
else
{
int mid=(node[n].l+node[n].r)/2;
if (rr<=mid) search(ll,rr,2*n);
else if (ll>mid) search(ll,rr,2*n+1);
else
{
search(ll,mid,2*n);
search(mid+1,rr,2*n+1);
}
}
}
int main()
{
int L,T,Q;
while(scanf("%d%d%d",&L,&T,&Q)!=EOF)
{
build(1,L,1);
char ss;
while(Q--)
{
getchar();
scanf("%c",&ss);
if(ss=='C')
{
int ll,rr,v;
scanf("%d%d%d",&ll,&rr,&v);
updata(ll,rr,v,1);
}
else
{
int ll,rr;
int i;
for(i=1;i<=T;i++)
{
hash[i]=0;
}
scanf("%d%d",&ll,&rr);
search(ll,rr,1);
int all=0;
for(i=1;i<=T;i++)
{
all+=hash[i];
}
printf("%d\n",all);
}
}
}
return 0;
}
struct data
{
int l,r,val;
}node[300009];
bool hash[39];
inline int max(int a,int b)
{
return a>b?a:b;
}
void build(int ll,int rr,int n)
{
node[n].l=ll;
node[n].r=rr;
node[n].val=1;
if (ll==rr) return ;
int mid=(ll+rr)/2;
build(ll,mid,2*n);
build(mid+1,rr,2*n+1);
}
void updata(int ll,int rr,int a,int n)
{
if(node[n].val==a)return ;
if (node[n].l==ll&&node[n].r==rr)
{
node[n].val=a;
return ;
}
if(node[n].val!=-1)
{
node[n+n].val=node[n].val;
node[n+n+1].val=node[n].val;
node[n].val=-1;
}
int mid=(node[n].l+node[n].r)/2;
if (rr<=mid) updata(ll,rr,a,2*n);
else if (ll>=mid+1) updata(ll,rr,a,2*n+1);
else
{
updata(ll,mid,a,2*n);
updata(mid+1,rr,a,2*n+1);
}
}
void search(int ll,int rr,int n)
{
if(node[n].l<=ll&&node[n].r>=rr&&node[n].val!=-1)//所问区间在 已知结点的范围内,标记后,返回
{
hash[node[n].val]=1;
return;
}
else
{
int mid=(node[n].l+node[n].r)/2;
if (rr<=mid) search(ll,rr,2*n);
else if (ll>mid) search(ll,rr,2*n+1);
else
{
search(ll,mid,2*n);
search(mid+1,rr,2*n+1);
}
}
}
int main()
{
int L,T,Q;
while(scanf("%d%d%d",&L,&T,&Q)!=EOF)
{
build(1,L,1);
char ss;
while(Q--)
{
getchar();
scanf("%c",&ss);
if(ss=='C')
{
int ll,rr,v;
scanf("%d%d%d",&ll,&rr,&v);
updata(ll,rr,v,1);
}
else
{
int ll,rr;
int i;
for(i=1;i<=T;i++)
{
hash[i]=0;
}
scanf("%d%d",&ll,&rr);
search(ll,rr,1);
int all=0;
for(i=1;i<=T;i++)
{
all+=hash[i];
}
printf("%d\n",all);
}
}
}
return 0;
}