51 15 17 13 35 5Sample Output12110HintThis problem has huge input data,use scanf() instead of cin to read data to avoid time limit exceed.#----------------------------------------------------------------------------------------------#题目大意:按y的升序(y相同则按x升序)给出n(1<=n<=15000)个星星的坐标(0<=x,y<=32000),每个星星左下方(包括同一行或同一列)的星星个数为它的“等级”,依次输出等级为1,2,3,...,n-1的星星的个数。
最后提示用sanf,最好不用cin
#----------------------------------------------------------------------------------------------#
思路很容易:树状数组求x的“顺序对”,因为y已经按升序(即从低到高)排好序,所以只需要知道有多少个星星的x坐标小于当前星星的x坐标就可以了。
怎么用树状数组求x的“顺序对”呢,先解释下顺序对就是它之前的数当中比它小的数的个数。
然后,就容易了:将星星的x坐标的位置+1,当然是树状数组的+1,然后,x的getsum就是它的等级了。
why?
因为:x坐标+1,就表示了x那一排多了1个,而y坐标是递增的,每个点只有一个星星,所以当前x的getsum就代表了当前x坐标比它小的星星数量。
原谅我只能这样描述……自己体会吧。
代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lowbit(x) x&-xint n;int tr[32005];//树状数组int ans[15005];//存每个等级星星数void update(int q,int x){ for(int i=q;i<=32001;i+=lowbit(i))//注意i<=32001,这里我调了2天,之前写的是i<=32000,然而我x++了,所以…… tr[i]+=x;}int getsum(int q){ int ans=0; for(int i=q;i>0;i-=lowbit(i)) ans+=tr[i]; return ans;}//模板int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); x++;//为了防止x为0 update(x,1); ans[getsum(x)-1]++;//前面x++了,后边要减回来 } for(int i=0;i<n;i++) printf("%d/n",ans[i]);} By WZY
新闻热点
疑难解答