专栏文章

题解:P11993 [JOIST 2025] 迁移计划

P11993题解参与者 4已保存评论 4

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
4 条
当前快照
1 份
快照标识符
@mipgzpkr
此快照首次捕获于
2025/12/03 11:51
3 个月前
此快照最后确认于
2025/12/03 11:51
3 个月前
查看原文
看到深度相关肯定会想到 bfs 序,每次就是把一段区间里面的数加到另一段区间里面。但是你会发现由于是比较整体的一个操作,所以你维护这个 bfs 序其实是没啥用的。所以考虑对于每个深度整体维护一个集合。
这样子每次就是集合合并累加的过程。考虑对于每个深度维护一个线段树,下标为 dfs 序,向上合并就使用线段树合并。然后对于单点查询就是直接对于该深度进行 dfs 序子树查询即可。
时间复杂度 O(n+m)lognO(n+m)\log n
CPP
#include<bits/stdc++.h>
#define pb emplace_back
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long ll;
const int maxn=2e6+10;
int rt[maxn],c[maxn],dep[maxn],n,m;
int dfn[maxn],sz[maxn],id[maxn],cnt=0;
vector<int> G[maxn];
struct SegmentTree{
	#define mid (l+r>>1)
	int val[maxn*32],ls[maxn*32],rs[maxn*32],tot=0;
	void pushup(int p){ val[p]=val[ls[p]]+val[rs[p]]; }
	void modify(int& p,int l,int r,int x,int v){
		if(!p) p=++tot;
		if(l==r){ val[p]+=v; return ; }
		if(x<=mid) modify(ls[p],l,mid,x,v);
		else modify(rs[p],mid+1,r,x,v);
		pushup(p);
	}
	int query(int p,int l,int r,int ql,int qr){
		if(!p) return 0; int res=0;
		if(ql<=l&&r<=qr) return val[p];
		if(ql<=mid) res+=query(ls[p],l,mid,ql,qr); 
		if(qr>mid) res+=query(rs[p],mid+1,r,ql,qr);
		return res;
	}
	int merge(int p,int q,int l,int r){
		if(!p||!q) return p+q;
		if(l==r){ val[p]+=val[q]; return p; }
		ls[p]=merge(ls[p],ls[q],l,mid);
		rs[p]=merge(rs[p],rs[q],mid+1,r);
		pushup(p); return p;
	}
}seg;
void dfs(int u){
	dfn[u]=++cnt; id[cnt]=u; sz[u]=1;
	for(auto v:G[u]){ 
		dep[v]=dep[u]+1; 
		dfs(v); sz[u]+=sz[v]; 
	}
}
int main(){
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin>>n;
	for(int i=2;i<=n;i++){
		int fa; cin>>fa;
		G[fa].pb(i);
	}
	for(int i=1;i<=n;i++) cin>>c[i];
	dfs(1); cin>>m;
	for(int i=1;i<=n;i++)
		seg.modify(rt[dep[i]],1,n,dfn[i],c[i]);
	for(int i=1;i<=m;i++){
		int t; cin>>t;
		if(t==1){
			int X,Y; cin>>X>>Y;
			rt[Y]=seg.merge(rt[Y],rt[X],1,n);
			rt[X]=0;
		}else if(t==2){
			int A,L; cin>>A>>L;
			seg.modify(rt[dep[A]],1,n,dfn[A],L);
		}else{
			int B; cin>>B;
			cout<<seg.query(rt[dep[B]],1,n,dfn[B],dfn[B]+sz[B]-1)<<"\n";
		}
	}
	return 0;
}

评论

4 条评论,欢迎与作者交流。

正在加载评论...