1. 程式人生 > >洛谷P3835 【模板】可持久化平衡樹

洛谷P3835 【模板】可持久化平衡樹

題目背景

本題為題目 普通平衡樹 的可持久化加強版。

資料已經經過強化

感謝@Kelin 提供的一組hack資料

題目描述

您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作(對於各個以往的歷史版本):

  1. 插入x數

  2. 刪除x數(若有多個相同的數,因只刪除一個,如果沒有請忽略該操作)

  3. 查詢x數的排名(排名定義為比當前數小的數的個數+1。若有多個相同的數,因輸出最小的排名)

  4. 查詢排名為x的數

  5. 求x的前驅(前驅定義為小於x,且最大的數,如不存在輸出-2147483647)

  6. 求x的後繼(後繼定義為大於x,且最小的數,如不存在輸出2147483647)

和原本平衡樹不同的一點是,每一次的任何操作都是基於某一個歷史版本,同時生成一個新的版本。(操作3, 4, 5, 6即保持原版本無變化)

每個版本的編號即為操作的序號(版本0即為初始狀態,空樹)

輸入輸出格式

輸入格式:

第一行包含一個正整數N,表示操作的總數。

接下來每行包含三個整數,第 i 行記為 vi,opti,xi

vi表示基於的過去版本號( 0vi<i ),opti 表示操作的序號( 1opt6 ), xi 表示參與操作的數值

輸出格式:

每行包含一個正整數,依次為各個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%的資料滿足: 1n10

對於44%的資料滿足: 1n210^2

對於60%的資料滿足: 1n310^3

對於84%的資料滿足: 1n10^5

對於92%的資料滿足: 1n210^5

對於100%的資料滿足: 1n510^5 , 10^9xi10^9

經實測,正常常數的可持久化平衡樹均可通過,請各位放心

樣例說明:

共10次操作,11個版本,各版本的狀況依次是:

  1. [][]

  2. [9][9]

  3. [3, 9][3,9]

  4. [9, 10][9,10]

  5. [3, 9][3,9]

  6. [9, 10][9,10]

  7. [2, 9, 10][2,9,10]

  8. [2, 9, 10][2,9,10]

  9. [2, 10][2,10]

  10. [2, 10][2,10]

  11. [3, 9][3,9]

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 long long read()
  7 {
  8     long long x=0,f=1;
  9     char ch=getchar();
 10     while(ch>'9'||ch<'0')
 11     {
 12         if(ch=='-')
 13             f=-1;
 14         ch=getchar();
 15     }
 16     while(ch>='0'&&ch<='9')
 17     {
 18         x=x*10+ch-'0';
 19         ch=getchar();
 20     }
 21     return x*f;
 22 }
 23 const int maxn=5e5+5;
 24 struct node
 25 {
 26     int l,r,v,rd,sum;
 27 } e[maxn*50];
 28 int n,num,x,y,opt;
 29 int root[maxn];
 30 void update(int i)
 31 {
 32     if(!i)
 33         return ;
 34     e[i].sum=e[e[i].l].sum+e[e[i].r].sum+1;
 35 }
 36 int add(int x)
 37 {
 38     ++num;
 39     e[num].l=e[num].r=0;
 40     e[num].sum=1;
 41     e[num].v=x;
 42     e[num].rd=rand();
 43     return num;
 44 }
 45 int merge(int x,int y)
 46 {
 47     if(!x||!y)
 48         return x+y;
 49     if(e[x].rd>e[y].rd)
 50     {
 51         int p=++num;
 52         e[p]=e[x];
 53         e[p].r=merge(e[p].r,y);
 54         update(p);
 55         return p;
 56     }
 57     else
 58     {
 59         int p=++num;
 60         e[p]=e[y];
 61         e[p].l=merge(x,e[p].l);
 62         update(p);
 63         return p;
 64     }
 65 }
 66 void split(int now,int k,int &x,int &y)
 67 {
 68     if(now==0)
 69     {
 70         x=y=0;
 71         return ;
 72     }
 73     if(e[now].v<=k)
 74     {
 75         x=++num;
 76         e[x]=e[now];
 77         split(e[x].r,k,e[x].r,y);
 78         update(x);
 79     }
 80     else
 81     {
 82         y=++num;
 83         e[y]=e[now];
 84         split(e[y].l,k,x,e[y].l);
 85         update(y);
 86     }
 87 }
 88 void insert(int &root,int v)
 89 {
 90     int x=0,y=0,z=0;
 91     split(root,v-1,x,y);
 92     z=add(v);
 93     root=merge(merge(x,z),y);
 94 }
 95 void del(int &root,int v)
 96 {
 97     int x=0,y=0,z=0;
 98     split(root,v,x,z);
 99     split(x,v-1,x,y);
100     y=merge(e[y].l,e[y].r);
101     root=merge(merge(x,y),z);
102 }
103 int rank(int i,int k)
104 {
105     if(k==e[e[i].l].sum+1)
106         return e[i].v;
107     if(k<=e[e[i].l].sum)
108         return rank(e[i].l,k);
109     return rank(e[i].r,k-e[e[i].l].sum-1);
110 }
111 int query(int &root,int v)
112 {
113     int x,y;
114     split(root,v-1,x,y);
115     int ans=e[x].sum+1;
116     root=merge(x,y);
117     return ans;
118 }
119 int pre(int &root,int v)
120 {
121     int x,y,k;
122     split(root,v-1,x,y);
123     if(x==0)
124         return -2147483647;
125     k=e[x].sum;
126     int ans=rank(x,k);
127     root=merge(x,y);
128     return ans;
129 }
130 int nex(int &root,int v)
131 {
132     int x,y,ans;
133     split(root,v,x,y);
134     if(y==0)
135         return 2147483647;
136     ans=rank(y,1);
137     root=merge(x,y);
138     return ans;
139 }
140 int main()
141 {
142     n=read();
143     for(int i=1; i<=n; i++)
144     {
145         x=read(),opt=read(),y=read();
146         root[i]=root[x];
147         if(opt==1)
148             insert(root[i],y);
149         if(opt==2)
150             del(root[i],y);
151         if(opt==3)
152             printf("%d\n",query(root[i],y));
153         if(opt==4)
154             printf("%d\n",rank(root[i],y));
155         if(opt==5)
156             printf("%d\n",pre(root[i],y));
157         if(opt==6)
158             printf("%d\n",nex(root[i],y));
159     }
160     return 0;
161 }
View Code