题意:每个牛有两个属性值[S,E],如果牛i和牛j属性值满足Si <= Sj 且 Ej <= Ei 且 Ei - Si > Ej - Sj,牛i比牛j强壮,输出每个牛比自己强壮的牛的数量。
题解:把每个[Si,Ei],当做一个坐标点,会发现求的其实是每个点左上角有多少个点,那么可以把所有坐标点先按y降序排序然后x按升序,然后按用树状数组求和计算。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005;
struct Point {
int x, y, id;
}P[N];
int n, C[N], res[N];
bool cmp(Point a, Point b) {
if (a.y != b.y)
return a.y > b.y;
return a.x < b.x;
}
int lowbit(int x) {
return x & (-x);
}
int Sum(int x) {
int ret = 0;
while (x > 0) {
ret += C[x];
x -= lowbit(x);
}
return ret;
}
void Add(int x, int d) {
while (x <= N) {
C[x] += d;
x += lowbit(x);
}
}
int main() {
while (scanf("%d", &n) == 1 && n) {
memset(C, 0, sizeof(C));
for (int i = 0; i < n; i++) {
scanf("%d%d", &P[i].x, &P[i].y);
P[i].x++;
P[i].y++;
P[i].id = i;
}
sort(P, P + n, cmp);
for (int i = 0; i < n; i++) {
if (i > 0 && P[i - 1].x == P[i].x && P[i - 1].y == P[i].y)
res[P[i].id] = res[P[i - 1].id];
else
res[P[i].id] = Sum(P[i].x);
Add(P[i].x, 1);
}
for (int i = 0; i < n - 1; i++)
printf("%d ", res[i]);
printf("%d\n", res[n - 1]);
}
return 0;
}