区间更新+区间统计——pku2777
2011-07-12 10:55
190 查看
统计一定区间内颜色的不同种数
开个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
.l=ll;
node
.r=rr;
node
.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
.val==a)return ;
if (node
.l==ll&&node
.r==rr)
{
node
.val=a;
return ;
}
if(node
.val!=-1)
{
node[n+n].val=node
.val;
node[n+n+1].val=node
.val;
node
.val=-1;
}
int mid=(node
.l+node
.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
.l<=ll&&node
.r>=rr&&node
.val!=-1)//所问区间在 已知结点的范围内,标记后,返回
{
hash[node
.val]=1;
return;
}
else
{
int mid=(node
.l+node
.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;
}
开个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
.l=ll;
node
.r=rr;
node
.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
.val==a)return ;
if (node
.l==ll&&node
.r==rr)
{
node
.val=a;
return ;
}
if(node
.val!=-1)
{
node[n+n].val=node
.val;
node[n+n+1].val=node
.val;
node
.val=-1;
}
int mid=(node
.l+node
.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
.l<=ll&&node
.r>=rr&&node
.val!=-1)//所问区间在 已知结点的范围内,标记后,返回
{
hash[node
.val]=1;
return;
}
else
{
int mid=(node
.l+node
.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;
}
相关文章推荐
- 区间更新+区间统计(懒惰标记 模板)——pku3468
- 【线段树】PKU2777 区间更新区间询问(位优化)
- PKU 2777 Count Color (线段树区间更新)
- http://acm.pku.edu.cn/JudgeOnline/problem?id=2777 成段更新,区间统计颜色的种类 (用的位运算, 可是写的很搓)
- 线段树区间更新,区间统计 poj 2777 Count Color
- POJ 2777Count Color (线段树区间更新 + 位运算压缩)
- http://acm.pku.edu.cn/JudgeOnline/problem?id=3667 区间更新+求满足长短的最左区间
- poj(2777)——Count Color(lazy思想,成段更新,区间统计)
- POJ 2777 Count Color(区间更新 + 状压)
- poj 2777 线段树 区间更新+位运算
- POJ 2777 Count Color(线段树,区间更新,查询)
- PKU 2777 - Count Color(线段树 + 区间修改)
- POJ 2777 Count Color 线段树区间更新位运算
- 线段树区间更新,区间统计+离散化 POJ 2528 Mayor's posters
- poj 2777 区间统计
- 1036: [ZJOI2008]树的统计Count 【树链剖分】【点权:单点更新区间求值】
- POJ 2777 Count Color 线段树区间更新位运算
- PKU A Simple Problem with Integers (线段树区间更新求和)
- poj 2777 Count Color (线段树区间更新)
- POJ 2777 线段树区间查询区间更新