题解:
Treap的中序遍历是按照键值来排序后的序列,两点的lca为这个序列上区间权值的最小值。
现在只用考虑怎么求深度:
显然往前的一个权值比他大的会成为他的父亲,或者他们中间夹了一个更大的成为他的父亲。 其实就是求上升序列,然后套用常见套路即可。
#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&& (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=3e5+50;
int n,m,pos[N],ori[N],a[N];
struct query {int op,p,q;} q[N];
map <int,int> mp;
inline void init() {
n=rd();
vector <pii> vec;
for(int i=1;i<=n;i++) {
int op=rd();
if(op==0) {
q[i].op=1; q[i].p=++m;
pos[m]=rd(); a[m]=rd();
vec.push_back(pii(pos[m],m));
} else if(op==1) {
q[i].op=2; q[i].p=rd();
} else {
q[i].op=3; q[i].p=rd(); q[i].q=rd();
}
}
sort(vec.begin(),vec.end());
for(int i=0;i<m;i++) ori[i+1]=pos[vec[i].second], pos[vec[i].second]=i+1;
}
struct node {
pii mn;
int l1,r1,len1;
int l2,r2,len2;
inline void init(int v) {
mn=pii(v,0);
l1=r1=l2=r2=v;
len1=len2=1;
}
} tr[N*4];
inline int calcl(int k,int l,int r,int lim) {
if(l==r) return tr[k].mn.first>lim;
int mid=(l+r)>>1;
if(tr[k].l1>lim) return tr[k].len1;
else if(tr[k<<1|1].r1>lim) return tr[k].len1-tr[k<<1|1].len1+calcl(k<<1|1,mid+1,r,lim);
else return calcl(k<<1,l,mid,lim);
}
inline int calcr(int k,int l,int r,int lim) {
if(l==r) return tr[k].mn.first>lim;
int mid=(l+r)>>1;
if(tr[k].l2>lim) return tr[k].len2;
else if(tr[k<<1].r2>lim) return tr[k].len2-tr[k<<1].len2+calcr(k<<1,l,mid,lim);
else return calcr(k<<1|1,mid+1,r,lim);
}
inline void inc(int k,int l,int r,int p,int v) {
if(l==r) {
tr[k].init(v);
tr[k].mn.second=(v>=0) ? l : -1;
return;
} int mid=(l+r)>>1;
if(p<=mid) inc(k<<1,l,mid,p,v);
else inc(k<<1|1,mid+1,r,p,v);
tr[k].mn=max(tr[k<<1].mn,tr[k<<1|1].mn);
tr[k].l1=tr[k<<1|1].l1;
tr[k].r1=max(tr[k<<1|1].r1,tr[k<<1].r1);
tr[k].len1=tr[k<<1|1].len1+calcl(k<<1,l,mid,tr[k<<1|1].r1);
tr[k].l2=tr[k<<1].l2;
tr[k].r2=max(tr[k<<1].r2,tr[k<<1|1].r2);
tr[k].len2=tr[k<<1].len2+calcr(k<<1|1,mid+1,r,tr[k<<1].r2);
}
inline int ql(int k,int l,int r,int L,int R,int &lim) {
if(L>R) return 0;
if(L<=l && r<=R) {
int len=calcl(k,l,r,lim);
lim=max(lim,tr[k].r1);
return len;
} int mid=(l+r)>>1;
if(R<=mid) return ql(k<<1,l,mid,L,R,lim);
else if(L>mid) return ql(k<<1|1,mid+1,r,L,R,lim);
else {
int len=ql(k<<1|1,mid+1,r,L,R,lim);
len+=ql(k<<1,l,mid,L,R,lim);
return len;
}
}
inline int qr(int k,int l,int r,int L,int R,int &lim) {
if(L>R) return 0;
if(L<=l && r<=R) {
int len=calcr(k,l,r,lim);
lim=max(lim,tr[k].r2);
return len;
} int mid=(l+r)>>1;
if(R<=mid) return qr(k<<1,l,mid,L,R,lim);
else if(L>mid) return qr(k<<1|1,mid+1,r,L,R,lim);
else {
int len=qr(k<<1,l,mid,L,R,lim);
len+=qr(k<<1|1,mid+1,r,L,R,lim);
return len;
}
}
inline pii askmn(int k,int l,int r,int L,int R) {
if(L<=l && r<=R) return tr[k].mn;
int mid=(l+r)>>1;
if(R<=mid) return askmn(k<<1,l,mid,L,R);
else if(L>mid) return askmn(k<<1|1,mid+1,r,L,R);
else return max(askmn(k<<1,l,mid,L,R),askmn(k<<1|1,mid+1,r,L,R));
}
inline int askdep(int x) {
int val=askmn(1,1,m,x,x).first;
int r=val, t1=ql(1,1,m,1,x-1,r);
int l=val, t2=qr(1,1,m,x+1,m,l);
return t1+t2+1;
}
int main() {
init();
for(int i=1;i<N;i++) tr[i].mn=pii(-1,-1);
for(int i=1;i<=n;i++) {
if(q[i].op==1) {
inc(1,1,m,pos[q[i].p],a[q[i].p]);
mp[ori[pos[q[i].p]]]=pos[q[i].p];
} else if(q[i].op==2) {
inc(1,1,m,mp[q[i].p],-1);
} else {
int l=mp[q[i].p], r=mp[q[i].q];
if(l>r) swap(l,r);
int lca=askmn(1,1,m,l,r).second;
printf("%d\n",askdep(l)+askdep(r)-2*askdep(lca));
}
}
}
本文深入探讨了Treap数据结构的原理与实现,详细解释了如何利用Treap进行中序遍历排序,以及如何通过Treap解决特定的深度查询问题。文章提供了完整的代码示例,包括初始化、节点操作、查询最小值、更新节点等关键步骤,适用于需要高效处理排序和查询场景的开发者。
&spm=1001.2101.3001.5002&articleId=83024247&d=1&t=3&u=d6ab62b946d94de0bf8da215978fe626)
355

被折叠的 条评论
为什么被折叠?



