原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1556
分析: 属于更新区间,找点类型的题。
有树状数组,线段树两种方法,不用说也知道树状数组的简单些。
树状数组,里面存的是一段区间的染色次数。属于向前更新,向后查找。
线段树的话,节点里存有一段区间的染色次数,更新后,DFS一次得到每点的值。
我的代码(树状数组):
#include<stdio.h>
#include<string.h>
#define MAXN 100005
int C[MAXN];
int n;
int lowbit(int i)
{
return i&(-i);
}
void updata(int i,int m)
{
while(i>0)
{
C[i]+=m;
i-=lowbit(i);
}
}
int get_sum(int i)
{
int sum=0;
while(i<=n) {
sum+=C[i];
i+=lowbit(i);
}
return sum;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
memset(C,0,sizeof(C));
for(int i=0;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
updata( b,1);
updata( a-1,-1); //[a,b] 为染的次数。
}
for(int i=1;i<=n;i++) printf(i==n?"%d\n":"%d ",get_sum(i));
}
return 0;
}
我的代码(线段树):
#include<stdio.h>
#include<string.h>
#define MAXN 100005
struct Node
{
int l,r;
int num;
}segtree[MAXN<<2];
void build(int i,int l,int r)
{
segtree[i].l=l;
segtree[i].r=r;
segtree[i].num=0;
if(l==r) return ;
int mid=(l+r)>>1;
build( i*2, l, mid);
build( i*2+1,mid+1, r);
}
void Modfiy(int i,int x,int y)//区间[a,b]段加1;
{
//区间段的染色次数。
if(x==segtree[i].l&&y==segtree[i].r)
{
segtree[i].num+=1;
return ;
}
int mid=(segtree[i].l+segtree[i].r)>>1;
if(y<=mid)
Modfiy(i<<1,x, y);
else if(x>mid)
Modfiy(i<<1|1, x, y);
else
{
Modfiy(i<<1,x, mid);
Modfiy(i<<1|1, mid+1, y);
}
}
int ans[MAXN];
void DFS(int i)
{
for(int j=segtree[i].l;j<=segtree[i].r;j++) ans[j]+=segtree[i].num;
if(segtree[i].l==segtree[i].r) return ;
DFS( i<<1);
DFS( i<<1|1);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF&&n)
{
build(1,1,n);
for(int i=0;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
Modfiy(1,a,b);
}
memset(ans,0,sizeof(ans));
DFS(1);
// printf("OK?\n");
for(int i=1;i<=n;i++) printf(i!=n?"%d ":"%d\n",ans[i]);
}
return 0;
}
总结:还是树状数组的简单↖(^ω^)↗。。
今天再做这题的时候,数组直接复制了100000,果断WA了........o(>﹏<)o。——2013_9_9