OpenJ_Bailian - 2352 Stars(線段樹/樹狀陣列)
阿新 • • 發佈:2018-11-10
題意:統計幾級星的個數,對每個星星來說,有多少x,y都不超過他的星星,他就是幾級星(不包括自身);
題目給的星星是按y升序,y相等的時候x升序給出的,所以只需要知道每個星星前面有多少個x不超過他的就行;
很容易想到O(n2)的演算法,但時間複雜度太高;
這裡用線段樹或者樹狀陣列,每次輸入一次查詢一次x,在更新一次x;
用v表示結果,用t表示每個區間每個區間有多少個x的座標;
線段樹:
#include<cstdio> #include<iostream> using namespace std; const int maxn=32000+10;//x,y的最大值 int t[maxn<<2],v[maxn]; int ans,n,x,y; void query(int l,int r,int rt){//查詢x前面有多少個星星 if(x>=r) ans += t[rt]; else if(x<l) return; else{ int mid = (l+r)>>1; query(l,mid,rt<<1); query(mid+1,r,rt<<1|1); } } void update(int l,int r,int rt){//更新x所在的所有區間,l=r的時候是找到了子節點 if(l==r){ t[rt]++; return; } int mid = (l+r)>>1; if(x<=mid) update(l,mid,rt<<1); else update(mid+1,r,rt<<1|1); t[rt]++; } int main() { cin>>n; for(int i = 0;i < n;i++){ cin>>x>>y;//輸入一個操作一次 ans = 0;//ans是記錄前面有多少星 query(0,maxn,1); v[ans]++; update(0,maxn,1); } for(int i = 0;i < n;i++) cout<<v[i]<<endl; return 0; }
樹狀陣列:
#include<cstdio> #include<iostream> using namespace std; const int maxn=32000+10; int t[maxn],v[maxn]; int ans,n,x,y; int lowbit(int x){//查詢最低位的1 return x&(-x); } int query(int x){//查詢前x的和 int ans = 0;//ans是結果 while(x>0){//直到x減到0為止 ans += t[x];//ans每次加上當前的值 x -= lowbit(x);//x減去當前最低位的1 } return ans; } void update(int x){//更新x的值 while(x<=maxn){直到x增加到最大值 t[x]++;//當前區間加一 x += lowbit(x);//加上最低位的1 } return; } int main() { cin>>n; for(int i = 0;i < n;i++){ cin>>x>>y; x++;//防止x是0時的陷阱,最後統計每個級別的星的數量,不會影響那個結果 v[query(x)]++; update(x); } for(int i = 0;i < n;i++) cout<<v[i]<<endl; return 0; }