目录
Description
天文学家经常研究星图,星图上的星星由平面上的点表示,每颗星星都有笛卡尔坐标。一颗星星的等级是指该星星左下方的星星的数量.
例如,查看上图所示的地图,5号星的等级为3(左下方有1、2、4号星),2号星和4号星的等级为1。在这张地图上有一颗0级的星星,两颗1级的星星,一颗2级的星星,和一颗3级的星星。
你需要写一个程序来计算给定星图上每个等级的星星数量
Input
输入的第一行包括了星星的数量N (1<=N<=15000),下面N行描述了每颗星星的坐标(每一行由一个空格分隔两个整数X和Y组成, 0<=X,Y<=32000)。每一个点只会存在一颗星星。星星以Y坐标的升序排列。Y坐标相等的恒星按X坐标的升序排列。
Output
输出应该包括N行,每行一个数字。第一行为等级是0级的星星数量,第二行为等级是1级的星星数量,以此类推,最后一行为等级是N-1级的星星数量。
Sample Input
5
1 1
5 1
7 1
3 3
5 5Sample Output
1
2
1
1
0
题解:
经典的二维偏序问题,而且根据输入数据的限制,相当于降了一维,因为,默认输入的数据是 以Y坐标的升序排列,Y坐标相等的恒星按X坐标的升序排列。所以我们只需要找到在当前位置之前,且x坐标小于当前位置的x坐标的恒星的个数。
因此我们只需要考虑x坐标就行了,维护一个树状数组表示一段区间内小于当前位置的恒星的个数,常规的树状数组题目。
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
#define PI atan(1.0)*4
#define e 2.718281828
#define rp(i,s,t) for (i = (s); i <= (t); i++)
#define RP(i,s,t) for (i = (t); i >= (s); i--)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define push_back() pb()
#define fastIn \
ios_base::sync_with_stdio(0); \
cin.tie(0);
using namespace std;
inline int read()
{
int a=0,b=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')
b=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
a=(a<<3)+(a<<1)+c-'0';
c=getchar();
}
return a*b;
}
inline void write(int n)
{
if(n<0)
{
putchar('-');
n=-n;
}
if(n>=10)
write(n/10);
putchar(n%10+'0');
}
const int N=1e5+7;
int sum[N],ans[N];
int n;
int lowbit(int x){
return x&(-x);
}
int query(int i){
int res=0;
while(i>0){
res+=sum[i];
i-=lowbit(i);
}
return res;
}
void update(int i,int val){
while(i<=N){
sum[i]+=val;
i+=lowbit(i);
}
}
int main(){
n=read();
int i;
rp(i,0,n-1){
int x=read(),y=read();
x++;
ans[query(x)]++;//查询当前恒星之前,且x坐标小于当前位置的x坐标的横向个数,并记录。
update(x,1);//插入当前恒星,更新维护的树状数组
}
rp(i,0,n-1)
printf("%d\n",ans[i]);
return 0;
}