一开始做这题我是懵逼的,然后看了题解才懂。题目里有两个重要条件不能忽视,一个是给出的数据是以y为第一优先级,x为第二优先级给出来的,第二个是xy都是有范围的。
那么首先我们很容易想到这个算法:对每一个点(x0,y0),去找在他前面的点中的横坐标小于x0的有几个。这个算法的正确性是无需置疑的,因为数据是以y为第一优先级,x为第二优先级给出来的。
那么,问题就是,怎么实现这个算法呢?观察到第二个重要条件,x,y是有界的。
有界,我们可以想到什么呢?我想到一个问题,就是给了很多范围在1到100的数,让你排序。我们只要用num数组记录一下每个数出现的次数就好了。(这道题的统计也用到了这种方法)。这种方法的核心是四个字,维度变换。
我们再想,小于3的x,是不是等于等于1的x+等于2的x的总和?这是不是有点像sum?
到这里,算法就出来了。
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cstring>
using namespace std;
const int maxn=32005;
int n,tree[maxn],num[maxn];
int lowbit(int x)
{
return(x&(-x));
}
void add(int k)
{
while(k<=maxn)
{
tree[k]++;
k+=lowbit(k);
}
}
int read(int k)
{
int sum=0;
while(k)
{
sum+=tree[k];
k-=lowbit(k);
}
return sum;
}
int main(void)
{
int x,y;
while(cin>>n)
{
memset(tree,0,sizeof(tree));
memset(num,0,sizeof(num));
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
x++;
num[read(x)]++;
add(x);
}
for(int i=0;i<n;i++)
printf("%d\n",num[i]);
}
/*
for(int i=1;i<=7;i++)
{
printf("%d:%d\n",i,read(i));
}
*/
return 0;
}