Description:
平面内给出n个点的坐标,定义一个点的阶数为平面内横纵坐标都严格小于该点的点的数量(也就是平面内在该点的左下角的点数),问平面内的点的阶数都为多少.
Input:
n及n格点坐标
Output:
依次输出阶数为0到n-1的点的个数.
Analysis:
首先很明显用O(n^2)的暴力方式是要超时的,其实这题和上题求平面内矩形覆盖面积很像,我们不妨先把横坐标排好序,然后依次从前往后扫,只要同时维护在纵坐标数值区间内的点的个数就行,这里是单点修改,所以用树状数组就行啦。当然还要对纵坐标做个离散化,减少不必要的计算。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
#include<time.h>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
const int INF = 0xffffff0;
const int MOD = 1e9 + 7;
const int maxn = 15005;
int n;
pair<int,int> a[maxn];
int cnt[maxn];
int y[maxn],yc,id[32005];
int C[maxn];
void add(int x,int val){
while(x<=yc){
C[x]+=val;
x+=x&-x;
}
}
int sum(int x){
int ans=0;
while(x>0){
ans+=C[x];
x-=x&-x;
}
return ans;
}
int main() {
int n;scanf("%d",&n);
memset(cnt,0,sizeof(cnt));
memset(C,0,sizeof(C));
yc=0;
_for(i,0,n){
scanf("%d%d",&a[i].first,&a[i].second);
y[++yc]=a[i].second;
}
sort(a,a+n);
sort(y+1,y+yc+1);
yc=unique(y+1,y+yc+1)-(y+1);
for(int i=1;i<=yc;++i) id[y[i]]=i;
for(int i=0;i<n;++i){
pair<int,int> &now=a[i];
int idx=id[now.second];
int x=sum(idx);
cnt[x]++;
add(idx,1);
}
_for(i,0,n){
printf("%d\n",cnt[i]);
}
return 0;
}