CF226E Noble Knight's Path
XIII.CF226E Noble Knight's Path
这题分为在线和离线两种做法然而我只会在线
在线的思路很简单,即先树剖,然后建出主席树。主席树一维维护的是时间,每一棵主席树内部维护的是树剖剖出来的结果。
然后对于每一次询问:
首先先从两边跳链,找到LCA,并找出两点路径间没有被“亵渎”的城堡数。如果这一数量小于询问,直接输出。
否则,先从往上一直跳到LCA,如果这一段中未被“亵渎”的城堡数已经足够了,就直接输出;否则,从点向上跳,类似地找未被亵渎的城堡。
那怎么输出呢?这就要在线段树上二分了。当然,反正总复杂度已经是了,你要嫌麻烦直接写的二分套线段树也没有问题,毕竟线段树上二分写起来确实挺恶心的。不过这里写的还是线段树上二分。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100100;
int n,m,des[N];
//------------------------Chain Decompotision---------------
int dfn[N],rev[N],fa[N],dep[N],son[N],top[N],sz[N],head[N],cnt,tot;
struct node{
int to,next;
}edge[200100];
void ae(int u,int v){
edge[cnt].next=head[u],edge[cnt].to=v,head[u]=cnt++;
edge[cnt].next=head[v],edge[cnt].to=u,head[v]=cnt++;
}
void dfs1(int x,int Fa){
fa[x]=Fa,dep[x]=dep[Fa]+1,sz[x]=1;
for(int i=head[x],y;i!=-1;i=edge[i].next){
if((y=edge[i].to)==fa[x])continue;
dfs1(y,x),sz[x]+=sz[y];
if(sz[son[x]]<sz[y])son[x]=y;
}
}
void dfs2(int x){
if(son[x])top[son[x]]=top[x],dfn[son[x]]=++tot,rev[tot]=son[x],dfs2(son[x]);
for(int i=head[x],y;i!=-1;i=edge[i].next){
y=edge[i].to;
if(y==fa[x]||y==son[x])continue;
top[y]=y,dfn[y]=++tot,rev[tot]=y,dfs2(y);
}
}
//--------------Persistent Segment Tree--------------------
#define mid ((l+r)>>1)
int rt[N],newid;
struct SegTree{
int lson,rson,sum;
}seg[20001000];
void build(int &x,int l,int r){
x=++newid;
if(l!=r)build(seg[x].lson,l,mid),build(seg[x].rson,mid+1,r);
}
void modify(int &x,int y,int l,int r,int P){
if(l>P||r<P)return;
seg[x=++newid]=seg[y],seg[x].sum++;
if(l!=r)modify(seg[x].lson,seg[y].lson,l,mid,P),modify(seg[x].rson,seg[y].rson,mid+1,r,P);
}
int asksize(int x,int l,int r,int L,int R){
if(l>R||r<L)return 0;
if(L<=l&&r<=R)return seg[x].sum;
return asksize(seg[x].lson,l,mid,L,R)+asksize(seg[x].rson,mid+1,r,L,R);
}
int rangeask(int x,int y,int l,int r,int k){
if(l==r)return rev[l];
if((mid-l+1)-(seg[seg[y].lson].sum-seg[seg[x].lson].sum)>=k)return rangeask(seg[x].lson,seg[y].lson,l,mid,k);
else return rangeask(seg[x].rson,seg[y].rson,mid+1,r,k-((mid-l+1)-(seg[seg[y].lson].sum-seg[seg[x].lson].sum)));
}
int askkth(int x,int y,int l,int r,int L,int R,int &k,bool &findans){
if(l>R||r<L)return 0;
if(L<=l&&r<=R){
if((r-l+1)-(seg[y].sum-seg[x].sum)>=k){findans=true;return rangeask(x,y,l,r,k);}
else{k-=(r-l+1)-(seg[y].sum-seg[x].sum);return 0;};
}
int tmp=askkth(seg[x].lson,seg[y].lson,l,mid,L,R,k,findans);
if(findans)return tmp;
return askkth(seg[x].rson,seg[y].rson,mid+1,r,L,R,k,findans);
}
#define AS(A,B,L,R) (R-L+1)-(asksize(rt[B],1,n,L,R)-asksize(rt[A],1,n,L,R))
int main(){
scanf("%d",&n),memset(head,-1,sizeof(head));
for(int i=1,x;i<=n;i++){
scanf("%d",&x);
if(x)ae(x,i);
}
dfs1(1,0),top[1]=dfn[1]=rev[1]=tot=1,dfs2(1);
build(rt[0],1,n);
scanf("%d",&m);
for(int i=1,a,b,c,d,tp,res;i<=m;i++){
scanf("%d",&tp);
if(tp==1)scanf("%d",&a),des[a]=i,modify(rt[i],rt[i-1],1,n,dfn[a]);
else{
rt[i]=rt[i-1],res=0;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(des[a]<=d)c++;
int x=a,y=b,len=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
len+=AS(d,i,dfn[top[x]],dfn[x]),x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
len+=AS(d,i,dfn[x],dfn[y]);
len-=(des[b]<=d);
if(len<c){puts("-1");continue;}
//---------------------getpath&LCA-------------------------
int LCA=x;
x=a;
bool getans=false;
while(dep[x]>=dep[LCA]){
int anc=(dep[top[x]]<dep[LCA]?LCA:top[x]);
int tmp=AS(d,i,dfn[anc],dfn[x]);
if(c>tmp)c-=tmp,len-=tmp;
else{c=tmp-c+1;res=askkth(rt[d],rt[i],1,n,dfn[anc],dfn[x],c,getans);break;}
x=fa[top[x]];
}
if(getans){printf("%d\n",res);continue;}
//--------------------check A-----------------------------
y=b;
c=len-c+1;
if(des[b]<=d)c++;
while(true){
int dfntop=dfn[top[y]];
if(dep[top[y]]<=dep[LCA])dfntop=dfn[LCA]+1;
int tmp=AS(d,i,dfntop,dfn[y]);
if(c>tmp)c-=tmp;
else{c=tmp-c+1;res=askkth(rt[d],rt[i],1,n,dfntop,dfn[y],c,getans);break;}
y=fa[top[y]];
}
printf("%d\n",res);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?