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

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

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

做完这题:

对线段树有了理解

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

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

对于函数参数的理解:

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

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

区间更新+区间统计——pku2777 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 ;
}

你可能感兴趣的:(pku)