bzoj3196Tyvj 1730 二逼平衡樹


第一道樹套樹。
我用的是線段樹套伸展樹。

建樹方式:在線段樹的每一個節點上都建一棵伸展樹。舉個栗子,設在線段樹中,x節點管理l~r的數,在x這個節點的伸展樹,就按照傳統的方式,將l~r的(r-l+1)個數按照左大右小建伸展樹。對於空間的問題,伸展樹有logn層,仔細思考會發現每層只有n個數要插入,而n=50000。

對於4、5操作,按照以往的方式即可,但注意線段樹上左子樹和右子樹的返回值的比較。
對於3操作,將每一棵帶有pos位置的數,刪除再插入。
對於1操作,找到有多少個比其大的數+1,但問題在當該數不在隊列中時,找到的地址的數只是與它相近的,所以還要比較這兩個數的大小,如果該數還比找到的地址的數大,則加上它的個數(tr[x].n)
以上操作時間復雜度為nlogn^2
對於2操作,我們需要二分值求解,時間復雜度為nlogn^3,即找mid這個值在區間排名第幾,注意當返回的排名小於k的時候也要記錄。假設隊列為1 2 2 4,找排名為3的數,而當找到2時返回2的排名是2,而4的排名是4,這就說明了2~3都是2。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
struct node
{
int d,f,c,n,son[2];
}tr[4010000];int len;
struct tree
{
int l,r,lc,rc,root;
}t[210000];int tlen;
int a[51000];
void splay_add(int d,int f)
{
len++;
tr[len].d=d;tr[len].f=f;
tr[len].c=1;tr[len].n=1;
tr[len].son[0]=tr[len].son[1]=0;
if(tr[f].d>d)tr[f].son[0]=len;
else tr[f].son[1]=len;
}
void splay_update(int x)
{
int lc=tr[x].son[0],rc=tr[x].son[1];
tr[x].c=tr[lc].c+tr[rc].c+tr[x].n;
}
void splay_rotate(int x,int w)
{
int f=tr[x].f,ff=tr[f].f;
int r,R;

r=tr[x].son[w];R=f;
tr[R].son[1-w]=r;
if(r!=0)tr[r].f=R;

r=x;R=ff;
if(tr[ff].son[0]==f)tr[R].son[0]=r;
else tr[R].son[1]=r;
tr[r].f=R;

r=f;R=x;
tr[R].son[w]=r;
tr[r].f=R;

splay_update(f);
splay_update(x);
}
void splay_splay(int wt,int x,int rt)//wt表示這棵伸展樹在線段樹的那一個節點上
{
while(tr[x].f!=rt)
{
int f=tr[x].f,ff=tr[f].f;
if(ff==rt)
{
if(x==tr[f].son[0])splay_rotate(x,1);
else splay_rotate(x,0);
}
else
{
if(tr[f].son[0]==x&&tr[ff].son[0]==f){splay_rotate(f,1);splay_rotate(x,1);}
else if(tr[f].son[1]==x&&tr[ff].son[0]==f){splay_rotate(x,0);splay_rotate(x,1);}
else if(tr[f].son[0]==x&&tr[ff].son[1]==f){splay_rotate(x,1);splay_rotate(x,0);}
else if(tr[f].son[1]==x&&tr[ff].son[1]==f){splay_rotate(f,0);splay_rotate(x,0);}
}
}
if(rt==0)t[wt].root=x;
}
int splay_findip(int wt,int d)
{
int x=t[wt].root;
while(tr[x].d!=d)
{
if(tr[x].d>d)
{
if(tr[x].son[0]==0)break;
x=tr[x].son[0];
}
else if(tr[x].d<d)
{
if(tr[x].son[1]==0)break;
x=tr[x].son[1];
}
}
return x;
}
void splay_ins(int wt,int d)
{
int x=splay_findip(wt,d);
if(tr[x].d==d)
{
tr[x].n++;
splay_update(x);
splay_splay(wt,x,0);
}
else
{
splay_add(d,x);
splay_update(x);
splay_splay(wt,len,0);
}
}
void seg_bt(int l,int r)
{
tlen++;int now=tlen;
t[now].l=l;t[now].r=r;
splay_add(-2147483647,0);t[now].root=len;
splay_add(2147483647,len);splay_update(len-1);
for(int i=l;i<=r;i++)splay_ins(now,a[i]);
if(l<r)
{
int mid=(l+r)/2;
t[now].lc=tlen+1;seg_bt(l,mid);
t[now].rc=tlen+1;seg_bt(mid+1,r);
}
}
int splay_findrank(int wt,int d)
{
int x=splay_findip(wt,d);splay_splay(wt,x,0);
int ans=tr[tr[x].son[0]].c;
if(tr[x].d<d)ans+=tr[x].n;
return ans;
}
int seq_findrank(int now,int l,int r,int d)
{
if(t[now].l==l&&t[now].r==r)
{
return splay_findrank(now,d)-1;
}
int lc=t[now].lc,rc=t[now].rc;
int mid=(t[now].l+t[now].r)/2;
if(r<=mid) return seq_findrank(lc,l,r,d);
else if(mid+1<=l)return seq_findrank(rc,l,r,d);
else return seq_findrank(lc,l,mid,d)+seq_findrank(rc,mid+1,r,d);
}
void splay_del(int wt,int d)
{
int x=splay_findip(wt,d);splay_splay(wt,x,0);
if(tr[x].d!=d)return ;
if(tr[x].n>1){tr[x].n--;return ;}
else if(tr[x].son[0]!=0&&tr[x].son[1]==0){t[wt].root=tr[x].son[0];tr[tr[x].son[0]].f=0;}
else if(tr[x].son[0]==0&&tr[x].son[1]!=0){t[wt].root=tr[x].son[1];tr[tr[x].son[1]].f=0;}
else
{
int p=tr[x].son[0];
while(tr[p].son[1]!=0)p=tr[p].son[1];
splay_splay(wt,p,x);

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

t[wt].root=R;tr[R].f=0;
splay_update(R);
}
}
void seq_del(int now,int pos,int d)
{
splay_del(now,d);
if(t[now].l==t[now].r)return ;
int lc=t[now].lc,rc=t[now].rc;
int mid=(t[now].l+t[now].r)/2;
if(pos<=mid)seq_del(lc,pos,d);
else seq_del(rc,pos,d);
}
void seq_ins(int now,int pos,int d)
{
splay_ins(now,d);
if(t[now].l==t[now].r)return ;
int lc=t[now].lc,rc=t[now].rc;
int mid=(t[now].l+t[now].r)/2;
if(pos<=mid)seq_ins(lc,pos,d);
else seq_ins(rc,pos,d);
}
int splay_findqq(int wt,int d)
{
int x=splay_findip(wt,d);splay_splay(wt,x,0);
if(tr[x].d>=d&&tr[x].son[0]!=0)
{
x=tr[x].son[0];
while(tr[x].son[1]!=0)x=tr[x].son[1];
}
if(tr[x].d>=d)return 0;
return tr[x].d;
}
int seq_findqq(int now,int l,int r,int k)
{
if(t[now].l==l&&t[now].r==r)
{
return splay_findqq(now,k);
}
int lc=t[now].lc,rc=t[now].rc;
int mid=(t[now].l+t[now].r)/2;
if(r<=mid) return seq_findqq(lc,l,r,k);
else if(mid+1<=l)return seq_findqq(rc,l,r,k);
else return max(seq_findqq(lc,l,mid,k),seq_findqq(rc,mid+1,r,k));
}
int splay_findhj(int wt,int d)
{
int x=splay_findip(wt,d);splay_splay(wt,x,0);
if(tr[x].d<=d&&tr[x].son[1]!=0)
{
x=tr[x].son[1];
while(tr[x].son[0]!=0)x=tr[x].son[0];
}
if(tr[x].d<=d)return 999999999;
return tr[x].d;
}
int seq_findhj(int now,int l,int r,int k)
{
if(t[now].l==l&&t[now].r==r)
{
return splay_findhj(now,k);
}
int lc=t[now].lc,rc=t[now].rc;
int mid=(t[now].l+t[now].r)/2;
if(r<=mid) return seq_findhj(lc,l,r,k);
else if(mid+1<=l)return seq_findhj(rc,l,r,k);
else return min(seq_findhj(lc,l,mid,k),seq_findhj(rc,mid+1,r,k));
}
int main()
{
int n,m,mmax=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(mmax<a[i])mmax=a[i];
}
tlen=0;len=0;seg_bt(1,n);

int ops,l,r,pos,k;
while(m--)
{
scanf("%d",&ops);
if(ops==1)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",seq_findrank(1,l,r,k)+1);
}
else if(ops==2)
{
scanf("%d%d%d",&l,&r,&k);
int L=0,R=mmax,ans;
while(L<=R)
{
int mid=(L+R)/2;
int u=seq_findrank(1,l,r,mid)+1;
if(k<u)R=mid-1;
else {L=mid+1;ans=mid;}
}
printf("%d\n",ans);
}
else if(ops==3)
{
scanf("%d%d",&pos,&k);
seq_del(1,pos,a[pos]);
seq_ins(1,pos,k);a[pos]=k;
if(k>mmax)mmax=k;
}
else if(ops==4)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",seq_findqq(1,l,r,k));
}
else if(ops==5)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",seq_findhj(1,l,r,k));
}
}
return 0;
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com