快来嘲讽!MnZn 根号分治板子只有10pts
查看原帖
快来嘲讽!MnZn 根号分治板子只有10pts
219623
zcxxntietie楼主2023/3/9 10:18
#include<bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
const int maxn=2e5+10;
const int N=300;
int n;
vector<int>e[maxn];
struct Q{int x,y,k;};
vector<Q>qs;
int val[maxn],dep[maxn],lg[maxn];
int f[maxn][20],fd[maxn][20];
inline void dfs(int x,int fa)
{
    fd[x][0]=fa,dep[x]=dep[fa]+1;
    for(int i=1;i<=lg[dep[x]];i++) fd[x][i]=fd[fd[x][i-1]][i-1];
    for(auto y:e[x])if(y!=fa)dfs(y,x);
}
inline int jump(int x,int k)
{
	if(dep[x]<=k) return 0;
	int tag=dep[x]-k;
	for(int i=lg[dep[x]];i>=0;i--)
		if(dep[fd[x][i]]>=tag) x=fd[x][i];
	return x;	
}
inline void dfs(int x)
{
	for(int i=1;i<=N;i++)
		f[x][i]=f[jump(x,i)][i]+val[x];
	for(auto y:e[x]) if(y!=fd[x][0]) dfs(y);
}
inline int LCA(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=lg[dep[x]];i>=0;i--)
        if(dep[fd[x][i]]>=dep[y]) x=fd[x][i];
    if(x==y) return x;
    for(int i=lg[dep[x]];i>=0;i--)
        if(fd[x][i]!=fd[y][i]) x=fd[x][i],y=fd[y][i];
    return fd[x][0];
}
signed main()
{
	for(int i=2;i<maxn;i++) lg[i]=lg[i>>1]+1;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>val[i]; 
	for(int i=1,x,y;i<n;i++) cin>>x>>y,e[x].pb(y),e[y].pb(x);
	dfs(1,0),dfs(1); 
	for(int i=1,pre,x;i<=n;i++)
	{
		cin>>x;
		if(i>1)qs.pb({pre,x,0});
		pre=x;
	}
	for(int i=0,k;i<n-1;i++) cin>>k,qs[i].k=k;
	for(auto ele:qs)
	{
		int x=ele.x,y=ele.y,k=ele.k;
		int lca=LCA(x,y),ans=0;
		if(k>N)
		{
			int tmp1,tmp2;
			ans+=val[x]*(x!=lca)+val[y]*(y!=lca);
			while(dep[(tmp1=jump(x,k))]>=dep[lca]) ans+=val[tmp1],x=tmp1;
			while(dep[(tmp2=jump(y,k))]>=dep[lca]) ans+=val[tmp2],y=tmp2;
			if(tmp2==lca && tmp1==lca) ans-=val[lca];
			cout<<ans<<'\n';
		}
		else 
		{
			ans+=f[x][k]+f[y][k];
			int delta=(dep[x]-dep[lca])%k;
			if(!delta) ans-=(2*f[lca][k]-val[lca]);
			else  ans-=2*f[jump(lca,delta)][k];
			cout<<ans<<'\n';
		} 
	}
	return 0;
} 


2023/3/9 10:18
加载中...