这个题的线段树操作就相当于求个逆序数、但细节实现有些需要注意的
设每头牛的区间[x,y]
将所有区间按y降序排序,y相同时按x升序排序
这样一来y降序的情况下,后面某头牛的ans就是前面x比这头牛x小的个数,也就是求逆序数
但实际情况有些不一样,应为数据会出现x、y相等的情况
首先若x和y都相等,则复制前一头牛的ans
若只有y相等就要多注意下了:首先查询的时候还是查询[0,x]而不是[0,x-1],因为前面可能还有x和本x相等但y大于本y的,若查询[0,x-1]就把这一情况略过了。但查询[0,x]又会把前面和本x,y都相等的情况加进来,这里我的解决办法是直接爆了回搜减去x,y同时相等的个数,只能说幸好数据没卡这一点,庆幸没超时
剩下的直接查询[0,x]就是了
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lch p<<1
#define rch p<<1|1
#define mid (t[p].l+t[p].r)>>1;
#define MAXN 100005
struct node
{
int l,r;
int sum;
}t[MAXN<<2];
struct cows
{
int x,y;
int idx;
int ans;
}c[MAXN];
bool cmp1(const cows &a,const cows &b)
{
if(a.y==b.y) return a.x<b.x;
else return a.y>b.y;
}
bool cmp2(const cows &a,const cows &b) {return a.idx<b.idx;}
void construct(int l,int r,int p)
{
t[p].l=l,t[p].r=r,t[p].sum=0;
if(l==r) return ;
int m=mid;
construct(l,m,lch);
construct(m+1,r,rch);
}
void modify(int x,int p)
{
if(t[p].l==t[p].r)
{
t[p].sum++;
return ;
}
int m=mid;
if(x<=m) modify(x,lch);
else modify(x,rch);
t[p].sum=t[lch].sum+t[rch].sum;
}
int query(int l,int r,int p)
{
if(t[p].l==l&&t[p].r==r)
return t[p].sum;
int m=mid;
if(r<=m) return query(l,r,lch);
else if(l>m) return query(l,r,rch);
else return query(l,m,lch)+query(m+1,r,rch);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF&&n)
{
int maxx=0;
for(int i=0;i<n;i++)
{
scanf("%d%d",&c[i].x,&c[i].y);
if(c[i].x>maxx) maxx=c[i].x;
c[i].idx=i;
}
sort(c,c+n,cmp1);
construct(0,maxx,1);
for(int i=0;i<n;i++)
{
int tans=0;
if(i>0&&c[i].y==c[i-1].y&&c[i].x==c[i-1].x)
tans=c[i-1].ans;
else if(i>0&&c[i].y==c[i-1].y)
{
int l=0,r=c[i].x;
if(l<=r) tans=query(l,r,1);
//幸好这一坨没超时
for(int j=i-1;j>=0;j--)
if(c[i].y==c[j].y&&c[i].x==c[j].x)
tans--;
else break;
}
else
{
int l=0,r=c[i].x;
if(l<=r) tans=query(l,r,1);
}
c[i].ans=tans;
modify(c[i].x,1);
}
sort(c,c+n,cmp2);
printf("%d",c[0].ans);
for(int i=1;i<n;i++) printf(" %d",c[i].ans);
printf("\n");
}
return 0;
}