计蒜客 棋子等级
问题描述
坐标系平面上有好多棋子,每个整点上至多有一个棋子。
假定棋子的等级是左下方的棋子个数,现在给出若干棋子的位置,求不同等级的棋子各有多少个。左下方包含正下和正右。说明(0, 0) 坐标的位置在左下角。
输入格式
第一行一个整数 N (1≤N≤100000)
接下来 N 行,一行两个整数 X,Y (0≤X,Y<100000),表示坐标。
数据保证坐标先按 Y 排序,再按 X 排序。
输出格式
N 行,每行一个整数,从 0 到 N−1 等级的棋子数量。
样例输入
5
1 1
5 1
7 1
3 3
5 5
样例输出
1
2
1
1
0
分析
由于Y坐标是递增给出的,因此这个题可以转换为求和问题。假设棋子A坐标为(X, Y),由于递增坐标是递增给出的,因此前面所有横坐标比X小的棋子都包含在棋子A的左下方。因此可以利用树状数组求和。
degree[A] = getsum(x)
代码
#include<iostream> #include<string> #include<cstring> #include <algorithm> #define MAX 100000 + 5 using namespace std; int n; int num[MAX]; int degree[MAX]; int lowbit(int x){ return x & (-x); } void build(int x, int v){ while(x <= MAX){ num[x] += v; x = x + lowbit(x); } } int getsum(int x){ int sum = 0; while(x > 0){ sum += num[x]; x = x - lowbit(x); } return sum; } int main(){ scanf("%d", &n); for(int i = 0; i < n; i++){ int a, b; scanf("%d %d", &a, &b); degree[getsum(a)]++; build(a, 1); } for(int i = 0; i < n; i++){ cout << degree[i] << endl; } return 0; }