3196 Tyvj 1730 二逼平衡樹

2021-08-03 18:47:48 字數 1750 閱讀 4875

題目比較簡潔:

您需要寫一種資料結構(可參考題目標題),來維護乙個有序數列,其中需要提供以下操作:

1.查詢k在區間內的排名

2.查詢區間內排名為k的值

3.修改某一位值上的數值

4.查詢k在區間內的前驅(前驅定義為小於x,且最大的數)

5.查詢k在區間內的後繼(後繼定義為大於x,且最小的數)

又有區間,又有排名,所以明顯是樹套樹了,反正我寫了區間線段樹套平衡樹。

相當於在每個線段樹上的點都開一棵splay,表示這個區間內的數的排名。

因為splay是動態開點的,所以時間o(nlog^2n)空間nlog^2n,都可以接受。

那麼二操作二分下答案,用一函式判斷合法性就可以了。

修改比較好做,刪了再增加。

前驅即把各個區間的答案(如果有的話)取最大值。

後繼同上,但取最小值。

**略長,做好心理準備。

code:

#include#include#include#include#include#includeusing namespace std;

const int inf=(1<<28);

struct trnodetr[2000010];int root[100010],trlen=0;

queue q;

int n,m,a[50010];

int read()

while(ch>='0'&&ch<='9')

return x*f;

}void update(int x)

int add(int d,int fa)

if(tr[x].son[0]==0&&tr[x].son[1]==0)

if(tr[x].son[0]!=0&&tr[x].son[1]==0)

if(tr[x].son[0]==0&&tr[x].son[1]!=0)

int p=tr[x].son[0];

while(tr[p].son[1]!=0) p=tr[p].son[1];

splay(p,x,rt);

root[rt]=p;tr[p].fa=0;q.push(x);

int r=p,r=tr[x].son[1];

tr[r].son[1]=r;

if(r!=0) tr[r].fa=r;

update(p);

}int findqianqu(int d,int rt)

splay(x,0,rt);

return x;

}int findhouji(int d,int rt)

splay(x,0,rt);

return x;

}int splayrank(int d,int rt)

int bt(int l,int r)

return x;

}void change(int x,int l,int r,int k,int c,int tmp,bool first)

int findrank(int x,int l,int r,int fl,int fr,int d)

int findnum(int fl,int fr,int k)

return ans;

}int solve1(int x,int l,int r,int fl,int fr,int d)

int main()

while(m--)

if(tmp==4)

if(tmp==5)

}}

3196 Tyvj 1730 二逼平衡樹

分析 帶區間查詢和名次詢問,線段樹套treap 操作1 查詢k在區間內的排名。求出k 1的名次 1就是k的名次 操作2 查詢區間內排名為k的值。二分列舉權值,呼叫操作1 操作3 修改某一位值上的數值。在樹上先刪除,再插入 操作4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 操作5.查詢k在區...

3196 Tyvj 1730 二逼平衡樹

time limit 10 sec memory limit 128 mb submit 2771 solved 1121 submit status discuss 您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值...

BZOJ3196 Tyvj 1730 二逼平衡樹

description 您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 in...