1 条题解
-
0
自动搬运
来自洛谷,原作者为

是青白呀
咕咕咕?咕咕咕!搬运于
2025-08-24 23:04:13,当前版本为作者最后更新于2024-11-06 21:26:10,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
不难发现所有经过的管道会形成一个树形的结构,每一个询问实际上等价于求两点在树上的 LCA。于是考虑把树求出来之后跑 LCA 算法即可做到 ,瓶颈在于树的点数是 级别的。
不难发现很多点是无效的,于是考虑对这棵树建立虚树,只保留 个叶子结点、 个既有左儿子、又有右儿子的分叉结点、以及 个询问结点。
首先对于每一层求出该层的分叉结点,可以通过使用树状数组维护路径经过点的横坐标的方式求出,每次需要的操作是后缀 和单点查询。
然后考虑建树。我们从第 层向第 层,由下往上扫描,维护当前层的每一个点在虚树上向下走遇到的(包含自己的)首个点的编号,需要支持的操作是的求第 个点的点值、单点修改以及合并两个相邻点。这些操作可以用 FHQ 维护,但常数较大。我们亦可以用线段树维护,额外在叶子上维护一个标记 ,其为 当且仅当这个点是某个合并形成的连续段的第一个点。此时求第 个点的下标可以用线段树上二分实现。于是对于每一层,我们先求出要合并的两个点的标号,并新建一个节点作为它们虚树上的父亲;再遍历该层的所有询问点,对于每个点查询线段树上维护的、虚树上下方首个点,然后新建一个点作为其父亲即可。注意所有新建点的操作都要同时在线段树上进行单点修改。
最后使用倍增、树剖、欧拉序等任意一种方式求 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; }
- 1
信息
- ID
- 8983
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者