这题比牛i强的牛的个数就是在图上的位置是除了本身,<= x, >= y,的区域的点的个数,就是左上方的个数,所以我们可以按y降序,x升序排列,建立线段树,求点左边的点的个数,要注意处理同样位置的牛。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define mem(a) memset(a, 0, sizeof(a))
#define maxn 100000
using namespace std;
long ans[maxn + 5], ress, flag;
struct tree
{
long sum;
}tr[maxn * 4 + 5];
struct point
{
long x;
long y;
long num;
}po[maxn + 5];
bool cmp(const struct point & a, const struct point & b)
{
if(a.y > b.y)
return true;
else if(a.y < b.y)
return false;
else if(a.y == b.y)
{
if(a.x < b.x)
return true;
else
return false;
}
}
void build(long l, long r, long n)
{
tr[n].sum = 0;
if(l == r)
return;
long mid = (l + r) / 2;
build(l, mid, n * 2);
build(mid + 1, r, n * 2 + 1);
}
void add(long l, long r, long n, long x)
{
if(flag == 1)
return;
tr[n].sum++;
if(l == r&&l == x)
{
flag = 1;
return;
}
long mid = (l + r) / 2;
if(x <= mid)
add(l, mid, n * 2, x);
else
add(mid + 1, r, n * 2 + 1, x);
}
void res(long l, long r, long n, long x)
{
if(r == x)
{
if(l == 0)
ress += tr[n].sum;
else
{
ress += tr[n].sum;
res(0, maxn, 1, l - 1);
}
return;
}
long mid = (l + r) / 2;
if(x <= mid)
res(l, mid, n * 2, x);
else
res(mid + 1, r, n * 2 + 1, x);
}
int main(int argc, char *argv[])
{
long num, x, y, i, tx, ty, tnum;
while(scanf("%ld", &num))
{
if(num == 0)
break;
mem(ans);
mem(tr);
mem(po);
build(0, maxn, 1);
for(i = 0;i < num;i++)
{
scanf("%ld%ld", &po[i].x, &po[i].y);
po[i].num = i;
}
sort(po, po + num, cmp);
for(i = 0;i < num;i++)
{
if(i != 0&&tx == po[i].x&&ty == po[i].y)
{
ans[po[i].num] = ans[tnum];
flag = 0;
add(0, maxn, 1, po[i].x);
continue;
}
ress = 0;
flag = 0;
res(0, maxn, 1, po[i].x);
ans[po[i].num] = ress;
flag = 0;
add(0, maxn, 1, po[i].x);
tx = po[i].x;
ty = po[i].y;
tnum = po[i].num;
}
for(i = 0;i < num;i++)
{
if(i != (num - 1))
printf("%ld ", ans[i]);
else
printf("%ld\n", ans[i]);
}
}
return 0;
}