题意:按照y升序给你n个星星的坐标,如果有m个星星的x,y坐标均小于等于星星A的坐标,那么星星A的等级为m。
分析:是一道树状数组题。举例来说,以下是题目的输入:
5
1 1
5 1
7 1
3 3
5 5
由于y坐标是升序的且坐标不重复,所以在星星A后面输入的星星的x,y坐标不可能都小于等于星星A。假如当前输入的星星为(3,3),易得我们只需要去找 树状数组中小于等于3的值就可以了,即GetSum(3)。注意:A[i]表示x坐标为i的个数,C[]为A[]的树状数组,那么GetSum(i)就是 序列中前i个元素的和,即x小于等于i的星星数。
本题还是一点要注意:星星坐标的输入可以是(0,0),所以我们把x坐标统一加1,然后用树状数组实现。
Java代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int[] star = new int[32005];
static int[] level = new int[15000];
public static void main(String[] args) throws NumberFormatException, IOException {
InputStreamReader is = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(is);
int a = Integer.parseInt(in.readLine());
int n = a;
while((a--) != 0)
{
String[] po = in.readLine().split(" ");
int x = Integer.parseInt(po[0]);
level[sum(x+1)]++;
update(x+1);
}
for(int i = 0; i < n; i++)
System.out.println(level[i]);
}
static int lowbit(int n)
{
return n&(-n);
}
static int sum(int n)
{
int ans = 0;
while(n != 0)
{
ans += star[n];
n -= lowbit(n);
}
return ans;
}
static void update(int n)
{
while(n < 32002)
{
star[n]++;
n += lowbit(n);
}
}
}
C++:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 32005;
int a[maxn], level[maxn], C[maxn];
void Update(int i, int value)
{
while(i <= maxn)
{
C[i] += value;
i += i & (-i);
}
}
int getsum(int i)
{
int s = 0;
while(i > 0)
{
s += C[i];
i -= i & (-i);
}
return s;
}
int main()
{
int n;
while(cin >> n)
{
int x, y;
memset(a, 0, sizeof(a));
memset(level, 0, sizeof(level));
memset(C, 0, sizeof(C));
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &x, &y);
int le = getsum(x+1);
a[x+1]++;
Update(x+1, 1);
level[le]++;
}
for(int i = 0; i < n; i++)
cout << level[i] << endl;
}
return 0;
}