(題目鏈結)
1.查詢k在區間內的排名;2.查詢區間內排名為k的值;3.修改某一位值上的數值;4.查詢k在區間內的前驅(前驅定義為小於x,且最大的數);5.查詢k在區間內的後繼(後繼定義為大於x,且最小的數)
修改不好搞,主席樹套樹狀陣列空間炸,最好的選擇→_→:線段樹套treap。
對於操作2,我們二分找到乙個排名大於$k$的最小的數,然後查詢這個數的前驅即可。
查詢前驅和後繼的時候要特判一下沒有找到的情況。
// bzoj3196#include#include#include#include#include#include#define ll long long
#define inf 2147483640
#define pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std;
const int maxn=50010;
int a[maxn],n,m;
struct node
};namespace treap
void rotate(int &x,int p)
void insert(int &k,int x)
int p=x>tr[k].val;tr[k].size++;
if (x==tr[k].val)
insert(tr[k][p],x);
if (tr[tr[k][p]].rnd>tr[k].rnd) rotate(k,p);
} void erase(int &k,int x)
if (tr[k][0]*tr[k][1]==0) k=tr[k][0]+tr[k][1];
else rotate(k,tr[tr[k][1]].rnd>tr[tr[k][0]].rnd),erase(k,x);
} else tr[k].size--,erase(tr[k][x>tr[k].val],x);
} int rank(int k,int x)
int find(int k,int x)
void modify(int k,int p,int val)
int rank(int k,int s,int t,int val)
int pref(int k,int s,int t,int val)
if (t<=mid) return pref(k<<1,s,t,val);
else if (s>mid) return pref(k<<1|1,s,t,val);
else return max(pref(k<<1,s,mid,val),pref(k<<1|1,mid+1,t,val));
} int suff(int k,int s,int t,int val)
if (t<=mid) return suff(k<<1,s,t,val);
else if (s>mid) return suff(k<<1|1,s,t,val);
else return min(suff(k<<1,s,mid,val),suff(k<<1|1,mid+1,t,val));
} int find(int s,int t,int k)
return pref(1,s,t,res); }}
using namespace segtree;
int main()
return 0;
}
BZOJ3196 Tyvj 1730 二逼平衡樹
description 您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 in...
bzoj3196 Tyvj 1730 二逼平衡樹
description 您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 in...
bzoj3196 Tyvj 1730 二逼平衡樹
傳送門 終於把這個大坑填完了。sb樹套樹 看似最不合理的方案恰恰是正確方案,樹套樹並不會mle,它的空間複雜度非常科學,o nlogn 結果因為空間算錯陣列開小神奇的t掉,浪費了我兩天時間 嘛。貌似除了操作二沒什麼好說的。轉換成判定性問題就好了,二分o nlog 3 n 解決。其他按照正常線段樹和平...