区间更新+区间统计——pku2777

统计一定区间内颜色的不同种数

开个hash,在search随时记录颜色数目

做完这题:

对线段树有了理解

更新操作时,线段树用遗传的方法,在一个区间异化时,将有用信息遗传到子代(仅仅是子代,不是所有的子孙都遗传,这样就节约了时间)

统计操作时,线段树用了区间统计(不是统计每个叶子),统计未被异化的区间(不是所有子孙都统计,又节约时间了)

对于函数参数的理解:

当传入的是结点下标n时,函数里考虑n+n,n+n+1的子树

而不仅传入有下标,还有区间时,就要分区间是在当前树的左子树,或是右子树,或是区间同时在左右子树

View Code
#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;
}
原文地址:https://www.cnblogs.com/huhuuu/p/2104015.html