题目描述
夜空中有N颗恒星(N≤100000),每颗恒星具有其坐标(x, y)(0≤x, y≤100000)。现在,天文学家要对这些恒星进行分类,分类的标准如下:对于任意一颗恒星S(x,y),如果存在k颗恒星,其x, y坐标均不大于S,则恒星S属于k类星。
如下图所示:第5颗恒星为3类星,这是由1、2、4三颗恒星均在其左下方而得出的,类似地第2、4两颗恒星为1类星,第3颗恒星为2类星。因此在这幅图中只有一颗0类星,共有二颗1类星,2类星和3类星各有一颗。
现给出N颗恒星的坐标,要求统计出0~N-1类星的个数。
输入格式
输入文件第一行包含一个整数N,表示恒星总数。
接下来的N行每行两个整数表示一颗恒星的坐标。不存在两颗星拥有相同的坐标。
输出格式
输出文件包含N行,每行包含一个整数,第i行表示第i-1类星的数量。
样例数据
样例输入
5
3 3
5 1
5 5
1 1
7 1
样例输出
1
2
1
1
0
数据范围
对于20%的数据,n<=1000;
对于100%的数据, n<=100000;
题目分析
要统计左下方的点数
二维不好统计,先按照x从小到大排序,因此就只用统计下方的点数了。
可以使用树状数组轻松解决。
树状数组维护y坐标,插入后查询比他小的求和即可
源代码
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
map<int,int>M,M2;
map<int,int>::iterator it;
int n,m,f[500005],ans[500005];
struct node {
int x,y;
} a[500005];
const int Get_Int() {
int n=0,bj=1;
char x=getchar();
while(x<'0'||x>'9'){
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9'){
n=n*10+x-'0';
x=getchar();
}
return n*bj;
}
int Lowbit(int x) {
return x&-x;
}
void Add(int x,int d) {
for(int i=x; i<=m; i+=Lowbit(i))f[i]+=d;
}
int Ask(int r) {
int sum=0;
for(int i=r; i>=1; i-=Lowbit(i))sum+=f[i];
return sum;
}
bool cmp(node x,node y) {
if(x.x==y.x)return x.y<=y.y;
return x.x<y.x;
}
int main() {
n=Get_Int();
for(int i=1; i<=n; i++) {
a[i].x=Get_Int()+1;
a[i].y=Get_Int()+1;
m=max(m,a[i].y);
}
sort(a+1,a+n+1,cmp);
for(int i=1; i<=n; i++) {
ans[Ask(a[i].y)]++;
Add(a[i].y,1);
}
for(int i=0; i<n; i++)printf("%d\n",ans[i]);
return 0;
}