1265. 數星星
阿新 • • 發佈:2022-02-12
樹狀陣列
開始,橫座標可能為 \(0\),所以需要偏移一位
題目連結
1265. 數星星
天空中有一些星星,這些星星都在不同的位置,每個星星有個座標。
如果一個星星的左下方(包含正左和正下)有 \(k\) 顆星星,就說這顆星星是 \(k\) 級的。
例如,上圖中星星 \(5\) 是 \(3\) 級的(\(1,2,4\) 在它左下),星星 \(2,4\) 是 \(1\) 級的。
例圖中有 \(1\) 個 \(0\) 級,\(2\) 個 \(1\) 級,\(1\) 個 \(2\) 級,\(1\) 個 \(3\) 級的星星。
給定星星的位置,輸出各級星星的數目。
換句話說,給定 \(N\) 個點,定義每個點的等級是在該點左下方(含正左、正下)的點的數目,試統計每個等級有多少個點。
輸入格式
第一行一個整數 \(N\),表示星星的數目;
接下來 \(N\) 行給出每顆星星的座標,座標用兩個整數 \(x,y\) 表示;
不會有星星重疊。星星按 \(y\) 座標增序給出,\(y\) 座標相同的按 \(x\) 座標增序給出。
輸出格式
\(N\) 行,每行一個整數,分別是 \(0\) 級,\(1\) 級,\(2\) 級,……,\(N−1\) 級的星星的數目。
資料範圍
\(1≤N≤15000,\)
\(0≤x,y≤32000\)
輸入樣例:
5
1 1
5 1
7 1
3 3
5 5
輸出樣例:
1
2
1
1
0
解題思路
樹狀陣列
由於是按縱座標為第一關鍵字排序,橫座標為第二關鍵字排序,按順序遍歷點,可保證前面的點在當前點的下面,同時如果縱座標相同,前面的點也只會在左邊,所以只需要統計左邊有多少點,可利用橫座標作為值域的樹狀陣列統計,另外樹狀陣列下標從 \(1\)
- 時間複雜度:\(O(n(log(3.2e4)))\)
程式碼
// Problem: 數星星 // Contest: AcWing // URL: https://www.acwing.com/problem/content/1267/ // Memory Limit: 64 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=3.2e4+5; int n,tr[N],res[N]; int ask(int x) { int res=0; for(;x;x-=x&-x)res+=tr[x]; return res; } void add(int x,int y) { for(;x<N;x+=x&-x)tr[x]+=y; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int a,b; scanf("%d%d",&a,&b); a++; res[ask(a)]++; add(a,1); } for(int i=0;i<n;i++)printf("%d\n",res[i]); return 0; }