1. 程式人生 > >Bzoj 3224.普通平衡樹 [ 權值線段樹 ]

Bzoj 3224.普通平衡樹 [ 權值線段樹 ]

Description

您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作:
1. 插入x數
2. 刪除x數(若有多個相同的數,因只刪除一個)
3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名)
4. 查詢排名為x的數
5. 求x的前驅(前驅定義為小於x,且最大的數)
6. 求x的後繼(後繼定義為大於x,且最小的數)

Input

第一行為n,表示操作的個數,下面n行每行有兩個數opt和x,opt表示操作的序號(1<=opt<=6)

Output

對於操作3,4,5,6每行輸出一個數,表示對應答案

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

權值線段樹 ,平衡樹 ,Treap , AVL , 替罪羊樹 , 樹狀陣列 都可以寫 博主提供一種權值線段樹的

AC code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define lson rt<<1 #define rson rt<<1|1 using namespace std; typedef long long ll; typedef pair<int,int>pii; const int maxn = 1e5+50; const int inf = 0x3f3f3f3f; const int mod = 1e9+7; struct segtree{ int l,r; int sum; }ss[maxn<<2]; struct Node{ int op; ll w; }node[maxn]; int
cnt = 0; ll vis[maxn]; void pushUp(int rt) { ss[rt].sum = (ss[lson].sum + ss[rson].sum); } void build(int l,int r,int rt) { ss[rt].l = l; ss[rt].r = r; ss[rt].sum = 0; if(l == r) return; int mid = (l+r)>>1; build(l,mid,lson); build(mid+1,r,rson); } void update(int pos,int val,int rt) { if ( ss[rt].l == ss[rt].r ) { ss[rt].sum += val; return; } int mid = (ss[rt].l + ss[rt].r) >> 1; if ( mid >= pos ) update(pos,val,lson); else update(pos,val,rson); pushUp(rt); } /********************************* re程式碼 re原因:當node[i].op 為 3 的時候tmp 有可能為1那麼tmp - 1 為零 l > r 條件永遠不滿足 因此re 在這個函式裡面加一句 if ( l > r ) return 0;也可以過 *********************************/ //int query(int l,int r,int rt) { // if ( ss[rt].l == l && ss[rt].r == r ) { // return ss[rt].sum; // } // int mid = (ss[rt].l + ss[rt].r) >> 1; // if ( mid >= r ) return query(l,r,lson); // else if ( l > mid ) return query(l,r,rson); // else return query(l,mid,lson) + query(mid+1,r,rson); //} /******************************** ac程式碼 ********************************/ int query(int l,int r,int rt) { if ( ss[rt].l >= l && ss[rt].r <= r ) { return ss[rt].sum; } int mid = (ss[rt].l + ss[rt].r) >> 1; int ans = 0; if ( mid >= l ) ans += query(l,r,lson); if ( r > mid ) ans += query(l,r,rson); return ans; } int Kth(int pos,int rt) { if ( ss[rt].l == ss[rt].r ) return ss[rt].l; int mid = (ss[rt].l + ss[rt].r ) >> 1; if ( ss[lson].sum >= pos ) { Kth(pos,lson); } else { Kth(pos-ss[lson].sum,rson); } } void Print(int l,int r,int rt) { if(l == r) { printf("ss[%d].sum = %d\n",ss[rt].l,ss[rt].sum); return; } int mid = (l+r)>>1; Print(l,mid,lson); Print(mid+1,r,rson); } int main(){ int t; cin>>t; for (int i = 1;i<=t;i++) { scanf("%d %lld",&node[i].op, &node[i].w ); if ( node[i].op != 4 ) vis[++cnt] = node[i].w; } sort(vis+1,vis+cnt+1); int len = unique(vis+1,vis+cnt+1) - vis; len--; // printf("len = %d\n",len); // for (int i = 1;i<=len;i++) printf("%lld ",vis[i]); // printf("\n"); build(1,len,1); for (int i = 1;i<=t;i++) { int tmp; if ( node[i].op != 4 ) tmp = lower_bound(vis+1,vis+len+1,node[i].w) - vis; //printf("^ ^ %d %lld\n",tmp,vis[tmp]); if(node[i].op == 1) { update(tmp,1,1); //Print(1,len,1); } else if ( node[i].op == 2 ) { update(tmp,-1,1); } else if ( node[i].op == 3 ) { printf("%d\n",query(1,tmp-1,1)+1); } else if ( node[i].op == 4 ) { //printf("node[i].w = %lld, Kth() = %d\n",node[i].w,Kth(node[i].w,1)); printf("%lld\n",vis[Kth(node[i].w,1)]); } else if ( node[i].op == 5 ) { //printf("node[i].w = %lld ,tmp = %d\n",node[i].w,tmp); int ans = query(1,tmp-1,1); int temp = Kth(ans,1); //Print(1,len,1); //printf("ans = %lld ,temp = %d\n",ans,temp); printf("%lld\n",vis[temp]); } else if ( node[i].op == 6 ) { int ans = query(1,tmp,1); int temp = Kth(ans+1,1); printf("%lld\n",vis[temp]); } } return 0; }