目录
题目
坐标系平面上有好多棋子,每个整点上至多有一个棋子。
假定棋子的等级是左下方的棋子个数,现在给出若干棋子的位置,求不同等级的棋子各有多少个。左下方包含正下和正左。说明(0, 0) 坐标的位置在左下角。
输入格式
第一行一个整数 N (1≤N≤100000)
接下来 N 行,一行两个整数 X,Y (0≤X,Y<100000),表示坐标。
数据保证坐标先按 Y 排序,再按 X 排序。
输出格式
N 行,每行一个整数,从 0 到 N−1 等级的棋子数量。
样例输入
51 15 17 13 35 5样例输出
12110
题解:
知识点:
树状数组
分析:
我们先将坐标系压成坐标轴(黑笔表坐标和权值,蓝笔表题目输入的顺序):
那么这就显然易见了。题目保证 先按 Y 排序,再按 X 排序,故每当题目输入一对坐标,其对应的横坐标就会在我们压缩成的坐标轴上显示出来(我们这里是一行一行的处理,而不是一整组的处理!),则这个点的权值(答案)就是目前显示出来的其左边的棋子数量(之后显示出来的棋子不能算进去哦~不懂话就画流程图)。故可用树状数组维护。每次update的是1。核心代码:
cnt[getsum(++x)]++;//树状数组的下标从1开始,cnt是计数器
update(x);//更新
代码:
#include<iostream>
using namespace std;
const int N=1e5+5;
int n,C[N];
int cnt[N];
inline void c_plus(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
inline int lowbit(int x){
return x&-x;
}
int getsum(int x){
int res=0;
for (int i=x;i>0;i-=lowbit(i)){
res+=C[i];
}
return res;
}
void update(int x){
for (int i=x;i<=N;i+=lowbit(i)){
C[i]++;
}
}
int main(){
c_plus();
cin>>n;
for (int i=0;i<n;i++){
int x,y;
cin>>x>>y;
cnt[getsum(++x)]++;//树状数组的下标从1开始
update(x);//更新
}
for (int i=0;i<n;i++){
cout<<cnt[i]<<endl;
}
return 0;
}