【线段树】星
Time Limit:10000MS Memory Limit:65536K
Total Submit:125 Accepted:90
Case Time Limit:1000MS
Description
宇航员经常检测星图,在星图上,星星由点表示而且每颗星星都有笛卡尔坐标。星星的等级表示左下方(包含正左和正下方)星星的数量。宇航员想知道星星等级的分布。
例如,如上面图形所示,第5号星等级是3 (它由三个标记为1,2和4的星组成)。在此地图上,0等级的星星只有一个(1号),1等级的有两个(2和4号),2等级的有一个(3号),3等级的有一个(5号)。
你设计一个程序,在给定地图上计算出每个等级星星的数量。
Input
第一行包含N个星星(1<=N<=200000), 接下来的N行描绘星星的坐标(每行中有两个整数X和Y,由空格分开, 0<=X,Y<=32000)。 在图上的一点只能存在一颗星星,星星根据Y坐标的递增顺序排列,Y坐标相同的星星根据X坐标的递增顺序排列。
Output
包含N 行,一行一个数字,第一行包含0等级星星的数量,第二行包含1等级星星的数量,等等,最后一行包含N-1等级星星的数量。
Sample Input
5
1 1
5 1
7 1
3 3
5 5
Sample Output
1
2
1
1
0
1.我们可以先按y坐标由小到大排序,若两颗星星y相同,则按x坐标由小到大排序。
2.因为题目给出的数据范围是0<=x,y<=32000,所以我们相当于有了一个A数组,下标范围是0到32000,其中A[i]记录的是x坐标为i的星星的颗数。
那么,对于树状数组而言,C[i]= A[i–2k+ 1] + … + A[i],相当于记录了x坐标在[i-2k+1,i]这段区间中的星星的颗数。
3.按排序后的顺序,从左往右依次讨论每颗星星:
当讨论到坐标为(p,q)的星星时,只需查询区间[0,q]中星星的颗数就行了。因为前面讨论过的所有星星的y坐标都不会大于q。
查询完成后,再把该星星插入到树状数组中,即更新C数组中,所有包含了A[p]的元素的值。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn1 200005
#define maxn2 32005
#define lowbit(x) (x&(-x))
int ans[maxn1],a[maxn1],c[maxn1],maxx=-1;
void _read(int &x){
char tt=getchar();
while(tt<'0'||'9'<tt) tt=getchar();
for(x=0;'0'<=tt&&tt<='9';x=x*10+tt-'0',tt=getchar());
}
int getsum(int x){
int s;
for(s=0;x;x-=lowbit(x))s+=c[x];
return s;
}
int main(){
int i,j,t,n;
_read(n);
for(i=1,t;i<=n;i++){
_read(a[i]);_read(t);
a[i]++;
maxx=max(maxx,a[i]);
}
for(i=1;i<=n;i++){
t=getsum(a[i]);
ans[t]++;
for(j=a[i];j<=maxx;j+=lowbit(j))c[j]++;
}
for(i=0;i<n;i++)
printf("%d\n",ans[i]);
}