可持久化非旋Treap
普通非旋Treap
看這裡
例題
洛谷P3835 【模板】可持久化平衡樹 題目描述 您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作(對於各個以往的歷史版本): 插入x數 刪除x數(若有多個相同的數,因只刪除一個,如果沒有請忽略該操作) 查詢x數的排名(排名定義為比當前數小的數的個數+1。若有多個相同的數,因輸出最小的排名) 查詢排名為x的數 求x的前驅(前驅定義為小於x,且最大的數,如不存在輸出-2147483647) 求x的後繼(後繼定義為大於x,且最小的數,如不存在輸出2147483647) 和原本平衡樹不同的一點是,每一次的任何操作都是基於某一個歷史版本,同時生成一個新的版本。(操作3, 4, 5, 6即保持原版本無變化) 每個版本的編號即為操作的序號(版本0即為初始狀態,空樹) 輸入輸出格式 輸入格式:
第一行包含一個正整數N,表示操作的總數。 接下來每行包含三個正整數,第 行記為 。 表示基於的過去版本號( $ 0 \leq v_i < i$ ), 表示操作的序號( $ 1 \leq opt \leq 6 $ ), 表示參與操作的數值
輸出格式:
每行包含一個正整數,依次為各個3,4,5,6操作所對應的答案
輸入輸出樣例 輸入樣例#1: 複製 10 0 1 9 1 1 3 1 1 10 2 4 2 3 3 9 3 1 2 6 4 1 6 2 9 8 6 3 4 5 8 輸出樣例#1: 複製 9 1 2 10 3 說明 資料範圍: 對於28%的資料滿足: $ 1 \leq n \leq 10 $ 對於44%的資料滿足: $ 1 \leq n \leq 2\cdot {10}^2 $ 對於60%的資料滿足: $ 1 \leq n \leq 3\cdot {10}^3 $ 對於84%的資料滿足: $ 1 \leq n \leq {10}^5 $ 對於92%的資料滿足: $ 1 \leq n \leq 2\cdot {10}^5 $ 對於100%的資料滿足: $ 1 \leq n \leq 5\cdot {10}^5 $ , 經實測,正常常數的可持久化平衡樹均可通過,請各位放心 樣例說明: 共10次操作,11個版本,各版本的狀況依次是:
可持久化平衡樹
(因為之前寫的被刪了所以就xjb寫吧) 辣雞csdn毀我青春
code
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define Max 20000000
#define max 2147483647
#define min -2147483647
using namespace std;
int tr[Max+1][2];
int sum[Max+1];
int fa[Max+1];
int heap[Max+1];
int num[Max+1];
int Root[Max+1];
int Now[Max+1];
int n,Q,i,j,k,l,x,y,X,Fs,Ls,I,J,type,root,Find,Find2,now,fa1,fa2;
void up(int t) {sum[t]=sum[tr[t][0]]+sum[tr[t][1]]+1;}
void New(int t,int x)
{
n++;
tr[n][0]=tr[tr[t][x]][0];
tr[n][1]=tr[tr[t][x]][1];
sum[n]=sum[tr[t][x]];
fa[n]=t;//不是原父親
num[n]=num[tr[t][x]];
heap[n]=rand()*32768+rand();
tr[t][x]=n;
}
void merge(int Fa,int son,int x,int y)
{
if (heap[x]<heap[y])
{
tr[Fa][son]=x;
fa[x]=Fa;
if (tr[x][1])
merge(x,1,tr[x][1],y);
else
{
sum[x]+=sum[y];
tr[x][1]=y;
fa[y]=x;
}
}
else
{
tr[Fa][son]=y;
fa[y]=Fa;
if (tr[y][0])
merge(y,0,x,tr[y][0]);
else
{
sum[y]+=sum[x];
tr[y][0]=x;
fa[x]=y;
}
}
if (Fa) up(Fa);
}
void split(int Fa1,int Fa2,int t,int k)
{
if (sum[tr[t][0]]>=k)
{
if (!fa1) fa1=t;
if (fa[t])
{
tr[fa[t]][tr[fa[t]][1]==t]=0;
up(fa[t]);
}
tr[Fa1][0]=t;
fa[t]=Fa1;
if (k && tr[t][0])
{
New(t,0);
split(t,Fa2,tr[t][0],k);
}
if (Fa1) up(Fa1);
}
else
{
if (!fa2) fa2=t;
if (fa[t])
{
tr[fa[t]][tr[fa[t]][1]==t]=0;
up(fa[t]);
}
tr[Fa2][1]=t;
fa[t]=Fa2;
if (tr[t][1])
{
New(t,1);
split(Fa1,t,tr[t][1],k-sum[tr[t][0]]-1);
}
if (Fa2) up(Fa2);
}
}
int find(int t,int k)
{
if (sum[tr[t][0]]>=k)
return find(tr[t][0],k);
else
if (sum[tr[t][0]]+1==k)
return num[t];
else
return find(tr[t][1],k-sum[tr[t][0]]-1);
}
void find1(int t,int s)
{
if (tr[t][0] && num[t]>=s)
find1(tr[t][0],s);
else
if (tr[t][1] && num[t]<s)
find1(tr[t][1],s);
if (num[t]<s)
{
Find2+=sum[tr[t][0]]+1;
if (num[t]>Find)
Find=num[t];
}
}
void find2(int t,int s)
{
if (tr[t][1] && num[t]<=s)
find2(tr[t][1],s);
else
if (tr[t][0] && num[t]>s)
find2(tr[t][0],s);
if (num[t]>s && num[t]<Find)
Find=num[t];
}
int gf(int t)
{
for (;fa[t];t=fa[t]);
return t;
}
int main()
{
srand(time(NULL));
scanf("%d",&Q);
n=0;
now=0;
fo(I,1,Q)
{
scanf("%d%d%d",&J,&type,&x);
root=0;
now=Now[J];
if (Root[J])
{
n++;
tr[n][0]=tr[Root[J]][0];
tr[n][1]=tr[Root[J]][1];
sum[n]=sum[Root[J]];
num[n]=num[Root[J]];
heap[n]=rand()*32768+rand();
root=n;
}
switch (type)
{
case 1:
{
n++;
num[n]=x;
sum[n]=1;
heap[n]=rand()*32768+rand();
j=n;
if (!Root[J])
{
now++;
root=n;
break;
}
Find=min;
Find2=0;
find1(root,x);
if (!Find2)
merge(0,0,n,root);
else
if (Find2==now)
merge(0,0,root,n);
else
{
fa1=0,fa2=0;
split(0,0,root,Find2);
merge(0,0,fa2,j);//注意這裡的n會變,所以要提前記錄
merge(0,0,gf(fa2),fa1);
}
root=gf(n);
now++;
break;
}
case 2:
{
if (!Root[J]) break;
Find=min;
Find2=0;
find1(root,x+1);
if (Find!=x) break;
Find=min;
Find2=0;
find1(root,x);
if (!Find2)
{
fa1=0,fa2=0;
split(0,0,root,1);
root=fa1;
}
else
if (Find2+1==now)
{
fa1=0,fa2=0;
split(0,0,root,now-1);
root=fa2;
}
else
{
fa1=0,fa2=0;
split(0,0,root,Find2);
j=fa1,k=fa2;
fa1=0,fa2=0;
split(0,0,j,1);
merge(0,0,k,fa1);
root=gf(k);
}
now--;
break;
}
case 3:
{
Find2=0;
find1(root,x);
printf("%d\n",Find2+1);
break;
}
case 4:
{
printf("%d\n",find(root,x));
break;
}
case 5:
{
Find=min;
Find2=0;
find1(root,x);
printf("%d\n",Find);
break;
}
case 6:
{
Find=max;
find2(root,x);
printf("%d\n",Find);
break;
}
}
Root[I]=gf(root);
Now[I]=now;
}
}