您的位置:首页 > 其它

POJ 2481 COWS(树状数组)

2015-04-06 21:01 363 查看
题目大意:

  说给你n个线段的,告诉你每个线段的起始点S_i,和终止点E_i, 问这n条线段里有多少线段是相互包含的,如果两个端点重合不算包含。

解题思路:

  用树状数组搞就可以了,这道题是star的变形题,star是让我们求出有多个星星在这个星星的左下角,而这道题是让我们求出有多少个星星在这个星星的左上角。

这样分析,对于(S_i,E_i)我们把他封装成为一个点的坐标,那么(S_j,E_j)同样也可以被封装成为一个点的坐标,而题目中说的S_i<S_j&&E_j<E_i&&E_i-S_i>E_j-S_j就是说j点在i点的左上角,且两点不能重合,好了,有了这个概念,我们只需要对于y按照从大到小排序,对于相同的y我们把x从小到大排序,用树状数组来维护就好了。

代码:

# include<cstdio>
# include<iostream>
# include<fstream>
# include<algorithm>
# include<functional>
# include<cstring>
# include<string>
# include<cstdlib>
# include<iomanip>
# include<numeric>
# include<cctype>
# include<cmath>
# include<ctime>
# include<queue>
# include<stack>
# include<list>
# include<set>
# include<map>

using namespace std;

const double PI=4.0*atan(1.0);

typedef long long LL;
typedef unsigned long long ULL;

# define inf 999999999
# define MAX 100000+4

struct node
{
int x;
int y;
int id;
}a[MAX];

int n;
int ans[MAX];
int tree[MAX];

int cmp ( node a,node b )
{
if ( a.y!=b.y )
return a.y > b.y;
else
return a.x < b.x;
}

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

void update ( int pos, int val )
{
while ( pos <= MAX )
{
tree[pos]+=val;
pos += pos&(-pos);
}
}

int main(void)
{
while ( cin>>n )
{
memset(tree,0,sizeof(tree));
memset(ans,0,sizeof(ans));
if ( n==0 )
break;

for ( int i = 0;i < n;i++ )
{
scanf("%d %d",&a[i].x,&a[i].y);
a[i].x++, a[i].y++;
a[i].id = i;
}
sort(a,a+n,cmp);

ans[a[0].id] = read(a[0].x);
update(a[0].x,1);
for ( int i = 1;i < n;i++ )
{
if ( a[i].x==a[i-1].x&&a[i].y==a[i-1].y )
{
ans[a[i].id]=ans[a[i-1].id];
}
else
{
ans[a[i].id]=read(a[i].x);
}
update(a[i].x,1);
}
printf("%d",ans[0]);
for ( int i = 1;i < n;i++ )
{
printf(" %d",ans[i]);
}
printf("\n");

}

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