poj 2481 Cows(树状数组)
Time Limit: 3000ms Memory Limit: 65536kB
Description
Farmer John’s cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his field is particularly good.
Farmer John has N cows (we number the cows from 1 to N). Each of Farmer John’s N cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval [S,E].
But some cows are strong and some are weak. Given two cows: cowi and cowj, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cowi is stronger than cowj.
For each cow, how many cows are stronger than her? Farmer John needs your help!
Input
The input contains multiple test cases.
For each test case, the first line is an integer N (1 <= N <= 105), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 105) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge.
The end of the input contains a single 0.
Output
For each test case, output one line containing n space-separated integers, the i-th of which specifying the number of cows that are stronger than cowi.
Sample Input
3
1 2
0 3
3 4
0
Sample Output
1 0 0
Hint
Huge input and output,scanf and printf is recommended.
Source
POJ Contest,Author:Mathematica@ZSU
这道题首先要排序,先按区间(interval)的右端点(e)从大到小排序,再按左端点(s)从小到大排序,这样一来越后面的区间越不容易被覆盖,所以每一个区间计算盖住他的区间时候只需考虑前面的点。由于右端点的有序性,只需要每次边更新边处理,看一看左端点比它小的有几个即可,还有一个小细节,考虑前面一样点的个数,查询后减去(注意计算前面一样点的个数也可以更新),因为根据题意这不必计算。
这个算法虽然有些绕,但是很常规,不难想到,那么问题是用什么数据结构去支持呢?可以用树状数组或线段树,线段树最近刚刚学会,那个时候我考虑了线段树的另一种编号方式,1,2,(1,2),3,4,(3,4),(1,4)…结果后来发现这就是树状数组。不得不说树状数组比线段树虽然多了位运算,乍一眼看不是很合直观,但是其代码简短一旦理解用起来得心应手。这道题就算树状数组的学习了。
Accepted 13424kB 576ms 1580 B G++
#define TEST
#undef TEST
#define MAX_N 100000
#define MAX_X (2<<16)
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
struct interval_type
{
int s,e,id,rank;
};
int compare1(const void* e1,const void* e2)
{
const interval_type* p1=(const interval_type *)e1;
const interval_type* p2=(const interval_type *)e2;
if (p1->e!=p2->e)
return p2->e-p1->e;
else
return p1->s-p2->s;
}
int compare2(const void* e1,const void* e2)
{
const interval_type* p1=(const interval_type *)e1;
const interval_type* p2=(const interval_type *)e2;
return p1->id-p2->id;
}
int n;
interval_type cow[MAX_N+1];
int tree[(MAX_X<<1)-1];
int same;
void insert(int x)
{
while (x<=(MAX_X<<1)-1)
{
tree[x]++;
x+=x&-x;
}
return;
}
int query(int x)
{
int ans=0;
while(x)
{
ans+=tree[x];
x-=x&-x;
}
return ans;
}
int main()
{
while (scanf("%d",&n)&&n)
{
for (int i=1;i<=n;i++)
scanf("%d%d",&cow[i].s,&cow[i].e);
cow[0].s=-1;
cow[0].e=-1;
for (int i=1;i<=n;i++)
cow[i].id=i;
qsort(cow+1,n,sizeof(interval_type),compare1);
memset(tree,0,sizeof(tree));
#ifdef TEST
for (int i=1;i<=n;i++)
printf("%d:(%d,%d)(%d)\n",cow[i].id,cow[i].s,cow[i].e,cow[i].rank);
#endif
same=0;
for (int i=1;i<=n;i++)
{
if (cow[i].s==cow[i-1].s && cow[i].e==cow[i-1].e)
same++;
else
same=0;
cow[i].rank=query(cow[i].s+1)-same;
insert(cow[i].s+1);
}
qsort(cow+1,n,sizeof(interval_type),compare2);
for (int i=1;i<=n;i++)
printf("%d%c",cow[i].rank,i==n?'\n':' ');
}
return 0;
}