您的位置:首页 > 理论基础 > 数据结构算法

POJ - 2481 Cows解题报告(树状数组 相同点重复计数处理)

2017-04-26 09:04 211 查看

题目大意:

给你好多的牛,10^5,然后再告诉你每个牛有一个闭区间,现在定义,如果一个牛a的区间是另一个牛b的区间的子区间,那么就说b就比a更强。显然就是让你求出对于每个牛来说,有多少牛比它更强。

分析:

现在应该就是把所有的区间都加到树状数组里面去,然后查询每个区间范围内有多少个完整的区间。但是要注意,有可能有两个完全相同的区间,那么根据xcx的公平哲学原理以及字母无关性等显然性质可知,这两个牛谁都不比谁强。

思路:

大概就是按照区间左端点坐标的递增顺序给这些区间排个序,然后按照这个顺序一个一个添加。每添加一个,那么找出这个区间的右端点右侧有多少个端点,就可以知道有多少牛比他强了。但是要注意一个

问题就是,这里面有可能有区间完全相同的情况。

相同区间的解决办法:

如果单纯的按照上述方法来做的话,就会把相同区间长度的牛也算在比他强的牛里面。

一开始我想到的处理办法是:对于每一块连续的区间起点的枚举,用book数组记录下他们的区间终点。在枚举下一块

连续的区间起点的时候,清空book数组。但是发现这样做最差的时间复杂度为O(n^2)还是超时了。

另外的办法就是,因为在枚举的时候,如果枚举到几个相同起点的区间的时候,他们的枚举顺序是区间终点从大到小,所以,如果上一个区间和这个区间完全相同,那么s++,如果不相同则s=0;这个s表示的就是连续出现了多少个完全相同的区间。

代码:

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>

#define maxn 100500

using namespace std;

struct qujian
{
int l;
int r;
int w;
}cow[maxn];
int tree[maxn]={0};
int n;

bool my_cmp(qujian a,qujian b)
{
if(a.l==b.l)return a.r>b.r;
return a.l<b.l;
}

int lowbit(int x)
{
return x&(-x);
}

void add(int x)
{
while(x<maxn)
{
tree[x]++;
x+=lowbit(x);
}
}

int sum(int x)
{
int s=0;
while(x>0)
{
s+=tree[x];
x-=lowbit(x);
}
return s;
}
int main()
{
int num[maxn]={0};
while(scanf("%d",&n))
{
memset(tree,0,sizeof(tree));
memset(num,0,sizeof(num));
if(n==0)return 0;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&cow[i].l,&cow[i].r);
cow[i].l++;
cow[i].r++;
cow[i].w=i;
}
sort(cow+1,cow+n+1,my_cmp);
int s=0;
for(int i=1;i<=n;i++)
{
num[cow[i].w]=sum(maxn-1)-sum(cow[i].r-1)-s;
add(cow[i].r);
if(cow[i].l==cow[i+1].l&&cow[i].r==cow[i+1].r)
{
s++;
}
else
{
s=0;
}
}
for(int i=1;i<=n;i++)
{
printf("%d ",num[i]);
}
cout<<endl;
}
}


后注:

本题另外一定要注意区间枚举的顺序,就是相同起点要按照区间终点从大到小枚举。具体实现见my_cmp()函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息