| Time Limit: 3000MS | Memory Limit: 65536K | |
| Total Submissions: 6854 | Accepted: 2211 |
Description
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: cow i and cow j, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cow i is stronger than cow j.
For each cow, how many cows are stronger than her? Farmer John needs your help!
Input
For each test case, the first line is an integer N (1 <= N <= 10 5), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 10 5) 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
Sample Input
3 1 2 0 3 3 4 0
Sample Output
1 0 0
题目大意:给你很多线段的头S和尾E,问每一条线段中包含了多少个线段,(S和E相同不计在内)。这题先一看,完全不知道什么方法,感觉非常的难办。
但是!树状数组可以轻松解决这个问题!!!首先,将她们线段的s和e当做是(s,e)一个点,这样子把所有点画出来,你就会发现一个很神奇的现象,题目要求就会变成:问每一个点的左上角有多少个点?
!!!这样不就和那题最简单的stars一样吗???!!!
stars那题是问左下角有多少个点,而这题是问左上角,而且点不是有序排好的,所以有些不同,特殊处理一下就可以。
如果正常做,那个y是递增的,所以sum和update那个方向就会相反了,这个其实没什么所谓,一样的,排序的时候先y由大到小排,y相同时x由小到大排,这样小小的处理,就变成stars那题了!!!
还有一点忘了,这题也是需要离散化的,离散化很重要很强大!!!
就这样!走过路过不要错过!!!
链接:http://poj.org/problem?id=2481
代码:
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <algorithm>
using namespace std;
struct node
{
int x, y, id;
}a[100005];
int n, b[100005], val[100005];
bool cmp1(node a, node b) //排序很重要!!!
{
if(a.y != b.y) return a.y > b.y; //先由大到小排y
return a.x < b.x; //y相同,x由小到大排
}
int lowbit(int i)
{
return i&(-i);
}
void update(int i, int x)
{
while(i <= 100005)
{
b[i] += x;
i += lowbit(i);
}
}
int sum(int i)
{
int sum = 0;
while(i > 0)
{
sum += b[i];
i -= lowbit(i);
}
return sum;
}
int main()
{
int i;
while(scanf("%d", &n), n)
{
memset(b, 0, sizeof(b));
memset(val, 0, sizeof(val));
for(i = 0; i < n; i++)
{
scanf("%d %d", &a[i].x, &a[i].y);
a[i].id = i;
a[i].x++; a[i].y++; //x与y都有可能为0,所以都++
}
sort(a, a+n, cmp1);
val[a[0].id] = sum(a[0].x); //val[]代表各点的sum()
update(a[0].x, 1);
for(i = 1; i < n; i++)
{
if(a[i].x == a[i-1].x && a[i].y == a[i-1].y) //若两区间相等
val[a[i].id] = val[a[i-1].id]; //该值等于上一个的值
else val[a[i].id] = sum(a[i].x);
update(a[i].x, 1); //更新该点x值
}
printf("%d", val[0]);
for(i = 1; i < n; i++)
{
printf(" %d", val[i]);
}
printf("\n");
}
return 0;
}
1483

被折叠的 条评论
为什么被折叠?



