dremio 實現類似官方create user sql 處理的思路
阿新 • • 發佈:2021-10-30
Treap
treap是啥,是一種平衡樹,tree+heap
眾所周知,二叉平衡樹一旦退化,複雜度將會很可怕。
treap則給每一個節點附上了一個隨機的值,然後利用旋轉操作,讓這個二叉搜尋樹同時也滿足堆的性質。期望下可以達到\(O(nlog_n)\)的複雜度了。
具體怎麼實現呢
大部分的操作和一般的二叉搜尋樹一樣。
插入
void insert(int &p,int v){ if(!p){ p=New(v); return ; } tr[p].size++; if(v==tr[p].v){ tr[p].cnt++; return ; } if(v<tr[p].v){ insert(tr[p].l,v); if(tr[p].rv<tr[tr[p].l].rv){ rr(p); } return ; }else{ insert(tr[p].r,v); if(tr[p].rv<tr[tr[p].r].rv){ lr(p); } } return ; }
可以注意到多了判斷兒子的隨機權值是否滿足堆的過程。
刪除
void del(int &p,int v){ if(!p) return ; tr[p].size--; if(tr[p].v==v){ if(tr[p].cnt>1){ tr[p].cnt--; return ; } if(!tr[p].l||!tr[p].r){ p=tr[p].l+tr[p].r; }else{ if(tr[tr[p].l].rv>tr[tr[p].r].rv){ rr(p); del(tr[p].r,v); }else{ lr(p); del(tr[p].l,v); } } return ; } if(v<tr[p].v){ del(tr[p].l,v); }else{ del(tr[p].r,v); } }
在連線左右兒子的時候需要判斷是否滿足堆的性質
最經典的模板題了
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; template<class T>inline void read(T &x) { x=0;register char c=getchar();register bool f=0; while(!isdigit(c))f^=c=='-',c=getchar(); while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar(); if(f)x=-x; } template<class T>inline void print(T x) { if(x<0)putchar('-'),x=-x; if(x>9)print(x/10); putchar('0'+x%10); } int n; int f; int x; struct tr{ int l; int r; int v; int cnt; int rv; int size; }tr[200005]; int ro; int cnt; int New(int val){ tr[++cnt].l=0; tr[cnt].r=0; tr[cnt].v=val; tr[cnt].cnt=1; tr[cnt].size=1; tr[cnt].rv=rand(); return cnt; } void update(int x){ tr[x].size=tr[tr[x].l].size+tr[tr[x].r].size+tr[x].cnt; } void rr(int &p){ int q=tr[p].l; tr[p].l=tr[q].r; tr[q].r=p; tr[q].size=tr[p].size; update(p); p=q; } void lr(int &p){ int q=tr[p].r; tr[p].r=tr[q].l; tr[q].l=p; tr[q].size=tr[p].size; update(p); p=q; } void insert(int &p,int v){ if(!p){ p=New(v); return ; } tr[p].size++; if(v==tr[p].v){ tr[p].cnt++; return ; } if(v<tr[p].v){ insert(tr[p].l,v); if(tr[p].rv<tr[tr[p].l].rv){ rr(p); } return ; }else{ insert(tr[p].r,v); if(tr[p].rv<tr[tr[p].r].rv){ lr(p); } } return ; } void del(int &p,int v){ if(!p) return ; tr[p].size--; if(tr[p].v==v){ if(tr[p].cnt>1){ tr[p].cnt--; return ; } if(!tr[p].l||!tr[p].r){ p=tr[p].l+tr[p].r; }else{ if(tr[tr[p].l].rv>tr[tr[p].r].rv){ rr(p); del(tr[p].r,v); }else{ lr(p); del(tr[p].l,v); } } return ; } if(v<tr[p].v){ del(tr[p].l,v); }else{ del(tr[p].r,v); } } int getpre(int v){ int p=ro; int res=0; while(p){ if(tr[p].v<v){ res=tr[p].v; p=tr[p].r; }else{ p=tr[p].l; } } return res; } int getsuf(int v){ int p=ro; int res=0; while(p){ if(tr[p].v<v){ res=tr[p].v; p=tr[p].r; }else{ p=tr[p].l; } } return res; } int getrank(int p,int v){ if(!p) return 0; if(tr[p].v==v) return tr[tr[p].l].size+1;//這裡扔的是size,這裡扔的是左兒子 if(tr[p].v<v) return getrank(tr[p].r,v)+tr[tr[p].l].size+tr[p].cnt; if(tr[p].v>v) return getrank(tr[p].l,v); } int getval(int p,int v){ if(!p) return 0; if(tr[tr[p].l].size>=v) return getval(tr[p].l,v); if(tr[tr[p].l].size+tr[p].cnt>=v) return tr[p].v; return getval(tr[p].r,v-tr[p].cnt-tr[tr[p].l].size); } int main(){ read(n); for(int i=1;i<=n;++i){ read(f); read(x); if(f==1) insert(ro,x); if(f==2) del(ro,x); if(f==3) printf("%d\n",getrank(ro,x)); if(f==4) printf("%d\n",getval(ro,x)); if(f==5) printf("%d\n",getpre(x)); if(f==6) printf("%d\n",getsuf(x)); } return 0; }
Rose只需要詢問前驅和後繼
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
template<class T>inline void read(T &x)
{
x=0;register char c=getchar();register bool f=0;
while(!isdigit(c))f^=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)x=-x;
}
template<class T>inline void print(T x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar('0'+x%10);
}
int n;
struct tr{
int l;int r;
int v;
int cnt;int rv;
}tr[500000];
int ro;
int cnt;
int a[500000];
int New(int v){
tr[++cnt].l=0;
tr[cnt].r=0;
tr[cnt].v=v;
tr[cnt].cnt=1;
tr[cnt].rv=rand();
return cnt;
}
void rr(int &p){
int q=tr[p].l;
tr[p].l=tr[q].r;
tr[q].r=p;
p=q;
return ;
}
void lr(int &p){
int q=tr[p].r;
tr[p].r=tr[q].l;
tr[q].l=p;
p=q;
return ;
}
void insert(int &p,int v){
if(!p){
p=New(v);
return ;
}
if(tr[p].v==v){
tr[p].cnt++;
return ;
}
if(tr[p].v<v){
insert(tr[p].r,v);
if(tr[p].rv<tr[tr[p].r].rv){
lr(p);
}
return ;
}else{
insert(tr[p].l,v);
if(tr[p].rv<tr[tr[p].l].rv){
rr(p);
}
return ;
}
}
int getpre(int v){
int p=ro;
int res=999999999;
while(p){
if(tr[p].v<=v){
res=tr[p].v;
p=tr[p].r;
}else{
p=tr[p].l;
}
}
return res;
}
int getsuf(int v){
int p=ro;
int res=999999999;
while(p){
if(tr[p].v>=v){
res=tr[p].v;
p=tr[p].l;
}else{
p=tr[p].r;
}
}
return res;
}
int ans;
int main(){
read(n);
read(ans);
insert(ro,ans);
for(int i=2;i<=n;++i){
read(a[i]);
//if(i!=1)
ans+=min(abs(a[i]-getpre(a[i])),abs(getsuf(a[i])-a[i]));
//else{
//ans=a[i];
// }
insert(ro,a[i]);
}
cout<<ans;
return 0;
}
注意一下前驅字尾的返回值
#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<stack>
#include<algorithm>
#define int long long
using namespace std;
template<class T>inline void read(T &x)
{
x=0;register char c=getchar();register bool f=0;
while(!isdigit(c))f^=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)x=-x;
}
template<class T>inline void print(T x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar('0'+x%10);
}
int t;
int ro;
int cnt;
struct tree{
int l;
int r;
int cnt;
int v;
int rv;
}tr[1000005];
int New(int x){
tr[++cnt].l=0;
tr[cnt].r=0;
tr[cnt].cnt=1;
tr[cnt].v=x;
tr[cnt].rv=rand();
return cnt;
}
void rr(int& p){
int q=tr[p].l;
tr[p].l=tr[q].r;
tr[q].r=p;
//tr[p].size=tr[q].size();
p=q;
}
void lr(int& p){
int q=tr[p].r;
tr[p].r=tr[q].l;
tr[q].l=p;
//tr[p].size=tr[q].size();
p=q;
}
void insert(int &p,int v){
if(!p) {
p=New(v);
return ;
}
if(v==tr[p].v){
tr[p].cnt++;
return ;
}
if(v<tr[p].v){
insert(tr[p].l,v);
if(tr[tr[p].l].rv>tr[p].rv){
rr(p);
}
return ;
}else{
insert(tr[p].r,v);
if(tr[tr[p].r].rv>tr[p].rv){
lr(p);
}
return ;
}
}
int cntt[2];
void del(int &p,int v){
if(!p){
return ;
}
if(tr[p].v==v){
if(tr[p].cnt>1){
tr[p].cnt--;
return ;
}
if(!tr[p].l||!tr[p].r){
p=tr[p].l+tr[p].r;
}else{
if(tr[tr[p].l].rv>tr[tr[p].r].rv){
rr(p);
del(tr[p].r,v);
}else{
lr(p);
del(tr[p].l,v);
}
}
return ;
}
if(v<tr[p].v){
del(tr[p].l,v);
}
if(v>tr[p].v){
del(tr[p].r,v);
}
}
int getpre(int v){
int p=ro;
int res=-999999999;
while(p){
if(tr[p].v<=v){
res=tr[p].v;
p=tr[p].r;
}else{
p=tr[p].l;
}
}
return res;
}
int getsuf(int v){
int p=ro;
int res=999999999;
while(p){
//cout<<p<<endl;
if(tr[p].v>=v){
res=tr[p].v;
p=tr[p].l;
}else{
p=tr[p].r;
}
}
return res;
}
int n;
int a,b;
int ans;
int mod=1000000;
signed main(){
read(n);
for(int i=1;i<=n;++i){
//cout<<i<<endl;
read(a);read(b);
if(cntt[a^1]){
int pp=getpre(b);
int ss=getsuf(b);
// cout<<"F";
if(b-pp<=ss-b){
ans+=b-pp;
ans%=mod;
del(ro,pp);
}else{
ans+=ss-b;
ans%=mod;
del(ro,ss);
}
// cout<<ans<<endl;
cntt[a^1]--;
}else{
insert(ro,b);
cntt[a]++;
}
}
cout<<ans%mod;
return 0;
}