题解(离线,DFN序树状数组)
2026-02-12 18:18:24
发布于:广东
6阅读
0回复
0点赞
由于危险值随时间增加,直接把 i 次询问危险值是否大于等于 k 转化为 1~i-k-1 的时间段有几个点有任务出现,离线处理将每个时间点的询问加入 vector, 然后对应地在树上查询。为了不用树剖可以使用 DFN 序树状数组,至于这个东西怎么做到的以后我会出文章讲所以你们现在自己找资料去。有多少个人接手任务的计算是容易的,通过 LCA 和 dep 数组就能轻易差分出来。
#include<bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
int n,m,tree[200005],head[200005],sz[200005],son[200005],top[200005],dep[200005],fa[200005],id[200005],ttl,cnt,op[200005],x[200005],y[200005],c[200005],ans[200005];
vector<int>tasks[200005];
struct node{int v,nxt;}t[400005];
void add(int x,int d){for(;x<=n;x+=x&-x)tree[x]+=d;}
int qry(int x){int res=0;for(;x;x^=x&-x)res+=tree[x];return res;}
void link(int x,int y){t[++cnt]={y,head[x]},head[x]=cnt,t[++cnt]={x,head[y]},head[y]=cnt;}
int read(){
int x=0,f=1,ch=getchar_unlocked();
for(;!isdigit(ch);ch=getchar_unlocked())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
void write(int x){
if(x<0)putchar_unlocked('-'),x=-x;
if(x>=10)write(x/10);
putchar_unlocked(x%10+'0');
}
void dfs1(int u,int lst){
dep[u]=dep[lst]+1,sz[u]=1,fa[u]=lst,id[u]=++ttl;
for(int i=head[u];i;i=t[i].nxt)
if(t[i].v^lst){
dfs1(t[i].v,u);
sz[u]+=sz[t[i].v];
if(sz[t[i].v]>sz[son[u]])son[u]=t[i].v;
}
}
void dfs2(int u,int topx){
top[u]=topx;
if(son[u])dfs2(son[u],topx);
for(int i=head[u];i;i=t[i].nxt)
if(t[i].v^fa[u]&&t[i].v^son[u])dfs2(t[i].v,t[i].v);
}
int lca(int u,int v){
while(top[u]^top[v])dep[top[u]]>dep[top[v]]?u=fa[top[u]]:v=fa[top[v]];
return dep[u]<dep[v]?u:v;
}
signed main(){
n=read();
for(int i=1;i<=n;++i)link(i,read());
dfs1(1,0),dfs2(1,1),m=read();
for(int i=1;i<=m;++i){
op[i]=read();
if(op[i]==1){x[i]=read(),y[i]=read(),c[i]=read();if(c[i]<i)tasks[i-c[i]-1].push_back(i);}
else x[i]=read();
}
for(int i=1;i<=m;++i){
if(op[i]==2)add(id[x[i]],1),add(id[x[i]]+sz[x[i]],-1);
for(int j:tasks[i]){int xyl=lca(x[j],y[j]);ans[j]=qry(id[x[j]])+qry(id[y[j]])-qry(id[xyl])-qry(id[fa[xyl]]);}
if(op[i]==1)write(dep[x[i]]+dep[y[i]]-(dep[lca(x[i],y[i])]<<1)+1),putchar_unlocked(' '),write(ans[i]),putchar_unlocked('\n');
}
return 0;
}
这里空空如也




有帮助,赞一个