Description
志向远大的YY小朋友在学完快速排序之后决定学习平衡树,左思右想再加上SY的教唆,YY决定学习Treap。友爱教教父SY如砍瓜切菜般教会了YY小朋友Treap(一种平衡树,通过对每个节点随机分配一个priority,同时保证这棵平衡树关于priority是一个小根堆以保证效率)。这时候不怎么友爱的510跑了出来,他问了YY小朋友一个极不和谐的问题:怎么求Treap中两个点之间的路径长度。YY秒了之后决定把这个问题交给你来做,但只要求出树中两点的LCA。
Input
第一行两个整数n,m
第二行n个整数表示每个元素的key
第三行n个整数表示每个元素的priority
接下m行,每行一条命令
I A B,插入一个元素,key为A, priority为B
D A,删除一个元素,key为A
Q A B,询问key分别为A和B的LCA的key
Output
对于每个Q输出一个整数。
Sample Input
2 2
1 2
4 5
Q 1 2
I 3 3
Sample Output
1
HINT
数据保证n<=10^5,m<=3*10^5
其余整数均不超过long的范围
数据保证任意时刻树中key和priority均不相同
题解
首先询问的两个点的key是一个区间
则lca的key是在这个区间内pri最小的
那么就变成了维护一个集合
支持查询区间最值,加入删除元素
线段树/平衡树
超时代码(想练splay结果超时了)
#include<bits/stdc++.h>
#define inf 2147483647
#define N 400005
#define M 1000005
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int c[N][2],fa[N],val[N],num[N],mn[N];
int n,m,tmp,cnt,rt,key[N],id[N];
void update(int x)
{
mn[x]=val[x];id[x]=x;
int l=c[x][0],r=c[x][1];
if (l&&mn[l]<mn[x]) mn[x]=mn[l],id[x]=id[l];
if (r&&mn[r]<mn[x]) mn[x]=mn[r],id[x]=id[r];
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
if (c[y][0]==x) l=0;else l=1;r=l^1;
if (y==k) k=x;
else if (c[z][0]==y) c[z][0]=x;else c[z][1]=x;
fa[x]=z;fa[y]=x;
c[y][l]=c[x][r];fa[c[x][r]]=y;
c[x][r]=y;
update(y);update(x);
}
void splay(int x,int &k)
{
int y,z;
while (x!=k)
{
y=fa[x],z=fa[y];
if (y!=k) if (c[z][0]==y^c[y][0]==x) rotate(x,k);else rotate(y,k);
rotate(x,k);
}
}
void insert(int &x,int k,int p,int f)
{
if (x==0){x=++cnt;num[x]=k;fa[x]=f;val[x]=mn[x]=p;id[x]=x;splay(x,rt);return;}
if (k>=num[x]) insert(c[x][1],k,p,x);
else insert(c[x][0],k,p,x);
}
void find_before(int x,int k)
{
if (x==0) return;
if (num[x]<k) tmp=x,find_before(c[x][1],k);
else find_before(c[x][0],k);
}
void find_after(int x,int k)
{
if (x==0) return;
if (num[x]>k) tmp=x,find_after(c[x][0],k);
else find_after(c[x][1],k);
}
void del(int k)
{
tmp=0;find_before(rt,k);
int l=tmp;
tmp=0;find_after(rt,k);
int r=tmp;
splay(l,rt);splay(r,c[rt][1]);
c[r][0]=0;update(r);update(l);
}
int query(int a,int b)
{
if (a>b) swap(a,b);
tmp=0;find_before(rt,a);
int l=tmp;
tmp=0;find_after(rt,b);
int r=tmp;
splay(l,rt);splay(r,c[rt][1]);
return num[id[c[r][0]]];
}
int main()
{
n=read();m=read();
insert(rt,-1,0,0);insert(rt,inf,0,0);
for (int i=1;i<=n;i++) key[i]=read();
for (int i=1;i<=n;i++)
{
int p=read();
insert(rt,key[i],p,0);
}
while(m--)
{
char ch[5];
scanf("%s",ch);
if (ch[0]=='I')
{
int k=read(),p=read();
insert(rt,k,p,0);
}
else if (ch[0]=='D')
{
int k=read();
del(k);
}
else
{
int a=read(),b=read();
printf("%d\n",query(a,b));
}
}
return 0;
}