悬赏关注
查看原帖
悬赏关注
565945
Azure__楼主2022/8/9 09:57

rt,查询第i-c时刻链x -> y上的和,用树状数组和树上差分维护。
评测记录:RE+WA
dfs和LCA应该没写错,代码中有注释,求dalao帮助,成功调好的一定关注,指出错误或提供hack数据也不尽感激.

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	char c; int x=0,f=1; c=getchar();
	while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); }
	while(c>='0'&&c<='9'){ x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
	return x*f;
}
int dep[200005],fa[200005][40],lg[200005],sz[200005],df[200005],n,m,tot;
//dep[i]:i号节点深度。   df[i]:i号节点的dfs序。  sz[i]:i号节点的孩子总数。
int c[200005],ans[200005],opt[200005],a[200005],b[200005];
// c:树状数组。 ans[i]:第i次操作产生的答案
vector<int> q[200005];// 记录询问的编号
vector<int> edge[200005];// 存边
inline void dfs(int k,int fath){
	fa[k][0]=fath; dep[k]=dep[fath]+1;
	if(k==0) dep[k]=0;
	else df[k]=++tot;
	sz[k]=1;
	for(register int i=1;i<=lg[dep[k]];i++){
		fa[k][i]=fa[fa[k][i-1]][i-1];
	}
	for(register int i=0;i<edge[k].size();i++){
		if(edge[k][i]!=fath){
			dfs(edge[k][i],k);
			sz[k]+=sz[edge[k][i]];
		}
	}
}
inline int LCA(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);
	while(dep[x]>dep[y]){
		x=fa[x][lg[dep[x]-dep[y]]-1];
	}
	if(x==y) return x;
	for(register int i=lg[dep[x]]-1;i>=0;i--){
		if(fa[x][i]!=fa[y][i]){
			x=fa[x][i]; y=fa[y][i];
		}
	}
	return fa[x][0];
}
inline int lowbit(int x){
	return x&(-x);
}
inline void updata(int x,int u){
	for(register int i=x;i<=n;i+=lowbit(i)){
		c[i]+=u;
	}
}
inline int sum(int x){
	int ans=0;
	for(register int i=x;i>0;i-=lowbit(i)){
		ans+=c[i];
	}
	return ans;
}
inline int ask(int x,int y){
	int lca=LCA(x,y);
	return sum(df[x])+sum(df[y])-sum(df[lca])-sum(fa[lca][0]);
}
int main()
{
	n=read();
	int root;
	for(register int i=1;i<=n;i++){
		int t=read();
		if(t==0) root=i;
		if(t!=0){
			edge[t].push_back(i);
		    edge[i].push_back(t);
		}
	}
	for(register int i=1;i<=n;i++){
		lg[i]=lg[i>>1]+1;
	}
	dfs(root,0);
	m=read();
    for(register int i=1;i<=m;i++){
    	opt[i]=read();
    	if(opt[i]==1){
    		a[i]=read(); b[i]=read(); int t=read();
    		q[i-t].push_back(i);
		}
		if(opt[i]==2){
			a[i]=read();
		}
	}
	for(register int i=1;i<=m;i++){
		for(register int j=0;j<q[i].size();j++){
			ans[q[i][j]]=ask(a[q[i][j]],b[q[i][j]]);
		}
		if(opt[i]==1){
			int d=dep[a[i]]+dep[b[i]]-2*dep[LCA(a[i],b[i])]+1;
			printf("%d %d\n",d,ans[i]);
		}
		if(opt[i]==2){
			updata(df[a[i]],1);
			updata(df[a[i]]+sz[a[i]]+1,-1);
		}
	}
	return 0;
}
2022/8/9 09:57
加载中...