题解:P11098 [ROI 2022 Day 1] 滑梯
不难发现所有经过的管道会形成一个树形的结构,每一个询问实际上等价于求两点在树上的 LCA。于是考虑把树求出来之后跑 LCA 算法即可做到
不难发现很多点是无效的,于是考虑对这棵树建立虚树,只保留
首先对于每一层求出该层的分叉结点,可以通过使用树状数组维护路径经过点的横坐标的方式求出,每次需要的操作是后缀
然后考虑建树。我们从第
最后使用倍增、树剖、欧拉序等任意一种方式求 LCA 即可。总复杂度
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define repp(i,j,k) for(int i=j;i>=k;i--)
#define ls(x) (x<<1)
#define rs(x) ((x<<1)|1)
#define mp make_pair
#define sec second
#define fir first
#define pii pair<int,int>
#define lowbit(i) i&-i
#define double long double
#define qingbai 666
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=5e5+5,M=6,S=(1<<8)+5,inf=1e9+7,mo=1e9+7;
const double eps=1e-8;
void read(int &p){
int x=0,w=1;
char ch=0;
while(!isdigit(ch)){
if(ch=='-')w=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
p=x*w;
}
int n,a[N],m,cntp,qid[N][2],bel[N*2];
pii q[N][2],p[N*2];
int cntn=0;
int pt[N];
struct BIT{
int t[N];
void add(int x,int v){
for(int i=x;i<=n;i+=lowbit(i))
t[i]+=v;
}
int query(int x){
int res=0;
for(int i=x;i;i-=lowbit(i))
res+=t[i];
return res;
}
}BIT;
vector<pii>targp[N];
vector<int>e[N*4];
struct seg{
int t[4*N],sum[4*N];
void pushup(int x){
sum[x]=sum[ls(x)]+sum[rs(x)];
}
void modifyn(int x,int le,int ri,int p,int v){
if(le==ri){
t[x]=v;
return;
}
int mid=(le+ri)>>1;
if(p<=mid)modifyn(ls(x),le,mid,p,v);
else modifyn(rs(x),mid+1,ri,p,v);
}
void modifys(int x,int le,int ri,int p,int v){
if(le==ri){
sum[x]=v;
return;
}
int mid=(le+ri)>>1;
if(p<=mid)modifys(ls(x),le,mid,p,v);
else modifys(rs(x),mid+1,ri,p,v);
pushup(x);
}
int queryp(int x,int le,int ri,int v,int op){
if(le==ri){
if(op)bel[op]=cntn,e[cntn].push_back(t[x]),t[x]=cntn;
return le;
}
int mid=(le+ri)>>1;
if(sum[ls(x)]>=v)return queryp(ls(x),le,mid,v,op);
else return queryp(rs(x),mid+1,ri,v-sum[ls(x)],op);
}
int queryn(int x,int le,int ri,int p){
if(le==ri)return t[x];
int mid=(le+ri)>>1;
if(p<=mid)return queryn(ls(x),le,mid,p);
else return queryn(rs(x),mid+1,ri,p);
}
}T;
int fa[N*4][20],dep[N*4];
pii ttp[N*4];
void dfs(int x,int f){
dep[x]=dep[f]+1;
fa[x][0]=f;
rep(i,1,19)
fa[x][i]=fa[fa[x][i-1]][i-1];
for(auto j:e[x])
dfs(j,x);
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
repp(i,19,0)
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(x==y)return x;
repp(i,19,0)
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
signed main(){
read(n);
rep(i,1,n)
read(a[i]),BIT.add(i,1);
rep(i,1,n){
pt[a[i]]=BIT.query(a[i]);
BIT.add(a[i]+1,-1);
}
read(m);
rep(i,1,m){
read(q[i][0].fir),read(q[i][0].sec),read(q[i][1].fir),read(q[i][1].sec);
if(q[i][0]>q[i][1])swap(q[i][0],q[i][1]);
q[i][0].fir++,q[i][0].sec++,q[i][1].fir++,q[i][1].sec++;
p[++cntp]=q[i][0],p[++cntp]=q[i][1];
}
sort(p+1,p+cntp+1),cntp=unique(p+1,p+cntp+1)-p-1;
rep(i,1,m){
qid[i][0]=lower_bound(p+1,p+cntp+1,q[i][0])-p;
qid[i][1]=lower_bound(p+1,p+cntp+1,q[i][1])-p;
}
rep(i,1,cntp)
targp[p[i].fir].push_back(mp(p[i].sec,i));
rep(i,1,n+1){
cntn++,ttp[i]=mp(n+1,i);
T.modifyn(1,1,n+1,i,cntn);
T.modifys(1,1,n+1,i,1);
}
for(auto j:targp[n+1])
bel[j.sec]=j.fir;
repp(i,n,1){
int targ=T.queryp(1,1,n+1,pt[i],0),nxtt=T.queryp(1,1,n+1,pt[i]+1,0);
int x=T.queryn(1,1,n+1,targ),y=T.queryn(1,1,n+1,nxtt);
T.modifys(1,1,n+1,nxtt,0);
cntn++,ttp[cntn]=mp(i,pt[i]);
e[cntn].push_back(x),e[cntn].push_back(y);
T.modifyn(1,1,n+1,targ,cntn);
int nid=cntn;
for(auto j:targp[i]){
if(j.fir==pt[i])bel[j.sec]=nid;
else cntn++,ttp[cntn]=mp(i,j.fir),T.queryp(1,1,n+1,j.fir,j.sec);
}
}
dfs(cntn,0);
rep(i,1,m){
int lcap=lca(bel[qid[i][0]],bel[qid[i][1]]);
printf("%d %d\n",ttp[lcap].fir-1,ttp[lcap].sec-1);
}
return 0;
}