一.题目
样例输入:
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;
}
四.补充
不用担心找不到所有的数,因为都可以找到