P3380 【模板】二逼平衡树(树套树)
题意
方法
线段树套平衡树
查询k的排名:把每个区间的排名加起来 O ( l o g n 2 ) O(log^2_n) O(logn2)
查询排名为k:不能相加,只能二分了 O ( l o g n 3 ) O(log^3_n) O(logn3)
修改:把包含这个数的区间对应的二叉树都修改了 O ( l o g n 2 ) O(log^2_n) O(logn2)
查询前驱:将每个区间的前驱取max O ( l o g n 2 ) O(log^2_n) O(logn2)
查询后继:将每个区间的后继取min O ( l o g n 2 ) O(log^2_n) O(logn2)
时间复杂度 O ( n ∗ l o g n 3 ) O(n*log^3_n) O(n∗logn3)
注意一下细节
心得
结构体方便
代码
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){
if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f==1?x:-x;
}
const int N=1e5+4,inf=2147483647;
int n,m,a[N];
namespace treap{
struct bala{
int w,siz,num,wei,ch[2];
}t[N*20];
int tot=0;
inline int newnode(int w){
t[++tot].w=w;
t[tot].wei=rand();
t[tot].num=t[tot].siz=1;
t[tot].ch[0]=t[tot].ch[1]=0;
return tot;
}
inline void pushup(int p){
t[p].siz=t[t[p].ch[1]].siz+t[t[p].ch[0]].siz+t[p].num;
}
inline void rotate(int &p,int d){
int y=t[p].ch[d];
t[p].ch[d]=t[y].ch[d^1];
t[y].ch[d^1]=p;
pushup(p);pushup(y);
p=y;
}
inline void insert(int &p,int w){
if(!p)p=newnode(w);
else if(t[p].w==w)++t[p].num;
else if(t[p].w>w){
insert(t[p].ch[0],w);
if(t[t[p].ch[0]].wei>t[p].wei)rotate(p,0);
}
else{
insert(t[p].ch[1],w);
if(t[t[p].ch[1]].wei>t[p].wei)rotate(p,1);
}
pushup(p);
}
inline void delet(int &p,int w){
if(t[p].w>w)delet(t[p].ch[0],w);
else if(t[p].w<w)delet(t[p].ch[1],w);
else{
if(t[p].num>1)t[p].num--;
else if(!t[p].ch[0]&&!t[p].ch[1])p=0;
else if(!t[p].ch[0]){
rotate(p,1);
delet(t[p].ch[0],w);
}
else if(!t[p].ch[1]){
rotate(p,0);
delet(t[p].ch[1],w);
}
else{
if(t[t[p].ch[0]].wei>t[t[p].ch[1]].wei){
rotate(p,0);
delet(t[p].ch[1],w);
}
else{
rotate(p,1);
delet(t[p].ch[0],w);
}
}
}
if(p)pushup(p);
}
inline int queryrank(int p,int k){
//+1
if(!p)return 0;
if(t[p].w>k)return queryrank(t[p].ch[0],k);
if(t[p].w==k)return t[t[p].ch[0]].siz;
return t[t[p].ch[0]].siz+t[p