您的位置:首页 > 其它

poj2481_树状数组

2012-08-19 11:11 169 查看
题意:FJ有n头牛(编号为1~n),每一头牛都有一个测验值[S, E],如果对于牛i和牛j来说,它们的测验值满足下面的条件则证明牛i比牛j强壮:Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj。现在已知每一头牛的测验值,要求输出每头牛有几头牛比其强壮。

分析:将[s,e]看成是而为坐标轴的横纵坐标,画出各个点,我们发现答案就是每个点左上的点的个数。将e降序,再将s升序,就可以转化成一维。

例如:

1 2
1 2
0 3
3 4,排序后为

3 4
0 3
1 2
1 2,这样就转化成横坐标前面小于它的个数。

这个题离散到大于等于1的范围内即可。

难点是,对重复坐标的处理,之前做过的题都是不会有重复的。

重复的点直接拷贝答案就行,不用getsum().

代码:

View Code

#include <stdio.h>
#include <iostream>
#include <memory.h>
#include <algorithm>
using namespace std;
const int maxnum=100005;
struct node
{
int l,r;
int pos;
}array[maxnum];
int tree[maxnum];
int ans[maxnum];
int n;

bool cmp(struct node a,struct node b)
{
if(a.r==b.r)
return a.l<b.l;
return a.r>b.r;
}

void update(int index,int add)
{
while(index<=maxnum)  //因为没有紧凑化,所以<=maxn;如果紧凑化到n个散列号的话,<=n就可以了
{
tree[index]+=add;
index+=(-index)&index;
}
}

int getsum(int index)
{
int sum=0;
while(index>0)
{
sum+=tree[index];
index-=(-index)&index;
}
return sum;
}

int main()
{
int i;
while(scanf("%d",&n) && n!=0)
{
for(i=0;i<n;i++)
{
scanf("%d%d",&array[i].l,&array[i].r);
array[i].pos=i;
}
sort(array,array+n,cmp);
memset(tree,0,sizeof(tree));
int cnt=0;
for(i=0;i<n;i++)
{
if(i!=0 && array[i].l==array[i-1].l && array[i].r==array[i-1].r)
{
ans[array[i].pos]=ans[array[i-1].pos]; //注意
cnt++;
}
//            else  这样为什么不行?????求助!!!!
//            {
//                update(array[i].l+1,1);
//                ans[array[i].pos]=getsum(array[i].l+1)-1+cnt;
//            }
else
ans[array[i].pos]=getsum(array[i].l+1);
update(array[i].l+1,1);
}
for(i=0;i<n-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[i]);
}
return 0;
}

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