洛谷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

 

posted @ 2019-01-06 09:27  ~liweilin~  阅读(258)  评论(12编辑  收藏  举报