BZOJ 3196 TYVJ 1730 二逼平衡樹

2021-08-14 15:54:36 字數 3976 閱讀 5080

k

在區間內的排名

2. 查詢區間內排名為

k的值

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

4. 查詢

k 在區間內的前驅(前驅定義為小於

x,且最大的數)

5. 查詢

k 在區間內的後繼(後繼定義為大於

x,且最小的數)

第一行兩個數n,

m 表示長度為

n 的有序序列和

m個操作

第二行有

n 個數,表示有序序列

下面有m行,o

pt表示操作標號 若o

pt=1

則為操作

1 ,之後有三個數l,

r,k表示查詢

k 在區間[l

,r]的排名 若o

pt=2

則為操作

2 ,之後有三個數l,

r,k表示查詢區間[l

,r] 內排名為

k 的數 若o

pt=3

則為操作

3 ,之後有兩個數po

s,k表示將po

s 位置的數修改為k

若opt

=4則為操作

4 ,之後有三個數l,

r,k表示查詢區間[l

,r] 內

k 的前驅 若o

pt=5

則為操作

5 ,之後有三個數l,

r,k表示查詢區間[l

,r] 內

k 的後繼

對於操作1,

2,4,

5各輸出一行,表示查詢結果

9 6

4 2 2 1 9 4 0 1 1

2 1 4 3

3 4 10

2 1 4 3

1 2 5 9

4 3 9 5

5 2 8 5

2 4

3 4 9n

和m的資料範圍:n,

m<=

50000

序列中每個數的資料範圍:[0

,1e8

] 雖然原題沒有,但事實上

5 操作的

k可能為負數

線段樹套平衡樹。

#include 

const

int maxn=50000;

const

int maxs=4000000;

const

int inf=0x3f3f3f3f;

struct splay_tree

inline

int updata(int x)

inline

int rotate(int x)

fa[x]=fa[f];

if(son[!k][x])

son[k][f]=son[!k][x];

fa[f]=x;

son[!k][x]=f;

updata(f);

updata(x);

return

0; }

inline

int splay(int &root,int x,int c)

else

if(t(x)==t(f))

else

}if(!c)

return

0; }

inline

int getkth(int root,int x)

else

if(size[son[0][now]]+cnt[now]0][now]]+1;

now=son[1][now];

}else

}return

0; }

inline

int ins(int &root,int x)

int now=root;

while(now)

else

else}}

return

0; }

inline

int del(int &root,int x)

else

splay(root,now,0);

if((!son[0][now])&&(!son[1][now]))

else

if(!son[0][now])

else

if(!son[1][now])

else

splay(root,w,root);

root=w;

fa[w]=0;

son[1][w]=son[1][now];

fa[son[1][now]]=w;

updata(w);

}return

0; }

inline

int getrank(int &root,int x)

else

else}}

return ans;

} int getpre(int now,int x)

else

if(val[now]int w=getpre(son[1][now],x);

if(w)

else

}else

} int getnext(int now,int x)

else

if(val[now]>x)

else

}else

}};int n,r[maxn+10];

inline

int max(int a,int b)

if(left==right)

int mid=(left+right)>>1;

build(now<<1,left,mid);

build(now<<1|1,mid+1,right);

return

0; }

int getrank(int now,int left,int right,int askl,int askr,int v)

int mid=(left+right)>>1,res=0;

if(askl<=mid)

if(mid1|1,mid+1,right,askl,askr,v);

}return res;

} int modify(int now,int left,int right,int pos,int v)

int mid=(left+right)>>1;

if(pos<=mid)

else

return

0; }

int getpre(int now,int left,int right,int askl,int askr,int v)

int mid=(left+right)>>1,res=0;

if(askl<=mid)

if(mid1|1,mid+1,right,askl,askr,v));

}return res;

} int getnext(int now,int left,int right,int askl,int askr,int v)

return st.val[f];

}int mid=(left+right)>>1,res=inf;

if(askl<=mid)

if(mid1|1,mid+1,right,askl,askr,v));

}return res;

}};segment_tree st;

int m,opt,a,b,c;

int main()

st.build(1,1,n);

while(m--)

scanf("%d",&c);

if(opt==1)

else

if(opt==2)

else

}printf("%d\n",left-1);

}else

if(opt==4)

else

}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 解決。其他按照正常線段樹和平...