題面
【題目描述】
天文學家常常檢查星星地圖,星星都有它的x,y座標,星星的等級的是左下方星星數量決定,包含正左和正下。
例如,看看上面的星圖。星星的等級爲 (由星星、和決定的)。星星的等級爲(由星星決定的)。在這張地圖上0級的星星有一顆,級的星星有兩顆,級的星星有一顆,級的星星有一顆,
你要編寫一個程序,計算每個等級的星星的數量。
【輸入】
第一行爲星星的數量。()
接下來行,每行爲星星的座標,用空格來分開(),每一個點上只有一個星星,按的升序給出座標,如果相同,則按照的升序給出。
【輸出】
輸出應該包含行,每行一個數字。第一行級星星的數量,第二行級星星的數量等等,最後一行包含星星的數量。
【樣例輸入】
5
1 1
5 1
7 1
3 3
5 5
【樣例輸出】
1
2
1
1
0
算法分析
乍一看好像是二維樹狀數組,但是本題降低了難度,對於輸入是按照:的升序給出座標,如果相同,則按照的升序給出。
那麼輸入第i顆星星的座標時,小於等於,小於等於,即左下角的星星已經全部出現了,且按照升序給出,因此,可以忽略座標,只需要找到小於等於的星星數量就是星星的級數。
設定數組,表示座標爲x的星星個數。
找小於等於的星星,即找前綴和。
需要注意,題目下標從0開始,而樹狀數組不能有下標爲0的情況,所以整體右移動一位。
當然也可以用二維樹狀數組實現。
【程序實現】
#include<bits/stdc++.h>
using namespace std;
#define N 32100
using namespace std;
int n,c[N],s[N],x[N],y[N];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int val)
{
while(x<=32001) //座標最大值爲32000
{
c[x]+=val;
x+=lowbit(x);
}
}
int sum(int x)
{
int ans=0;
while(x>0)
{
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x[i],&y[i]); //爲了避免出現0的情況,整體+1
s[sum(x[i]+1)]++; // 統計前綴和
update(x[i]+1,1); //單點增加
}
for(int i=0;i<n;i++)
printf("%d\n",s[i]);
return 0;
}