您的位置:首页 > 理论基础 > 计算机网络

线段树 http://acm.hdu.edu.cn/showproblem.php?pid=1556

2010-08-22 09:10 218 查看
方法一:

这个方法是网上看到的,太犀利了。 从起点开始坐标是1 ,结束的后一位是-1 ,在for 循环里用S叠加表示每个位置凃了几次!!

#include<iostream>
using namespace std;
int qs[100002];
void main()
{
int i,n,a,b,s;
while(scanf("%d",&n),n)
{
for(i=1;i<=n;i++)
qs[i]=0;
for(i=0;i<n;i++)
{
scanf("%d%d",&a,&b);
qs[a]++;qs[b+1]--;
}
printf("%d",qs[1]);s=qs[1];
for(i=2;i<=n;i++)
{
s+=qs[i];
printf(" %d",s);
}
printf("/n");
}
}


方法二:

线段树,Creat();update();query(); 三个步骤。 nod[i].v表示从nod[i].l到nod[i].r被涂过的次数。

#include <iostream>
[b]using namespace std;
#define MAXN 100001

struct {
int l,r,v;
}nod[3*MAXN];

int a[MAXN];

void Creat(int t,int l,int r)
{
nod[t].l=l;
nod[t].r=r;
nod[t].v=0;
if (l==r)
{
return ;
}
int mid=(l+r) / 2;
Creat(2*t,l,mid);
Creat(2*t+1,mid+1,r);
}

void Update(int t,int l,int r)
{
if (l==nod[t].l&&r==nod[t].r)
{
nod[t].v++;
return ;
}
if (nod[t].v>0)
{
nod[2*t].v+=nod[t].v;
nod[2*t+1].v+=nod[t].v;
nod[t].v=0;
}

if (r<=nod[2*t].r)
{
Update(2*t,l,r);
}
else if (l>=nod[2*t+1].l)
{
Update(2*t+1,l,r);
}
else
{
Update(2*t,l,nod[2*t].r);
Update(2*t+1,nod[2*t+1].l,r);
}
}

int query(int t,int index)
{
if (nod[t].l==nod[t].r)
{
return nod[t].v;
}
int mid;
mid=(nod[t].l+nod[t].r)/2;
if (index<=mid)    {
return nod[t].v+query(2*t,index);
}
else{
return nod[t].v+query(2*t+1,index);
}
}

int main()
{
int n;
int a,b;
while (cin>>n&&n)
{
int i;
Creat(1,1,n);
for (i=1;i<=n;i++)
{
cin>>a>>b;
Update(1,a,b);
}
int k;
for (i=1;i<=n;i++)
{
k=query(1,i);
cout<<k;
if (i==n)
{
cout<<endl;
}
else
{

cout<<" ";
}
}
}
return 0;
}

[/b]

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: