一.题目
样例输入:
5
7 1
5 1
5 5
3 3
1 1样例输出:
1
2
1
1
0
二.分析
有两个数据:x,y。
我们不妨先将x排序,再判断y,若小于,就++即可。
这是暴力的思路
for(int i=1;i<=n;i++){
int ans=0;
for(int j=1;j<=n && i!=j;j++)
if(a[j].y<=a[i].y)
ans++;
s[ans]++;
}
但这是O(n^2),肯定回超时。
这时,我们可以想到,不妨我们做累加,即统计这个数出现的个数。这样遇见比它大的数直接加上即可,不用再次遍历。
就是我们可以把每颗星星都看做一个点,比他大的数都要累加上1,若要看看小于i的星星的个数,求c【1到i】的值即可。(就是比它小的所有数出现的个数)。
这里可以用到树状数组。
三.参考代码
/*
5
7 1
5 1
5 5
3 3
1 1
*/
#include<bits/stdc++.h>
using namespace std;
struct node{
int x,y;
}data[1001];
int n;
int c[1001],s[1001]; //c为下边元素出现的次数,s为结果数组
bool cmp(node a,node b){
return a.x==b.x? a.y<b.y : a.x<b.x;
}
int sum(int x){
int ans=0;
for(int i=x;i>0;i-=(i&(-i))){
ans+=c[i];
}
return ans;
}
void updata(int x){
for(int i=x;i<=n;i+=(i&(-i))){
c[i]++;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
cin>>data[i].x>>data[i].y;
}
sort(data+1,data+1+n,cmp);
for(int i=1;i<=n;i++){
s[sum(data[i].y+1)]++;
updata(data[i].y+1);
}
for(int i=0;i<n;i++){
cout<<s[i]<<endl;
}
return 0;
}
四.补充
不用担心找不到所有的数,因为都可以找到