妹子刚学根号分治10pts又T又WA求捞
查看原帖
妹子刚学根号分治10pts又T又WA求捞
556545
Aaa_liang楼主2024/9/10 21:44

rt,思路大概是不加长链剖分优化的根号分治,只过了#1,#5#10 WA其余TLE,但不太理解为什么会TLE+WA,调了一个晚自习了求大佬捞捞QAQ

#include<cmath>
#include<iostream>
#define int long long
using namespace std;
const int N=5e4+5,M=250;
struct Edge{
	int l,nxt;
}edges[N<<1];
int n,bl,num[N],que[N],len[N],tt=1,head[N];
int fas[N][25],dep[N],sum[N][M];
void add_edge(int f,int l){
	edges[++tt]={l,head[f]};
	head[f]=tt;
}
void dfs(int x,int fa){
	dep[x]=dep[fa]+1,fas[x][0]=fa;
	for(int i=head[x];i;i=edges[i].nxt){
		int l=edges[i].l;
		if(l!=fa) dfs(l,x);
	}
}
int Kfa(int x,int k){
	for(int i=18;i>=0;i--){
		if((1<<i)>k) continue;
		k-=(1<<i);x=fas[x][i];
	}
	return x;
}
void Sum(int x){
	for(int j=1;j<=bl;j++){
		sum[x][j]=num[x];
		if(dep[x]<j) continue;
		sum[x][j]+=sum[Kfa(x,j)][j];
	}
	for(int i=head[x];i;i=edges[i].nxt){
		int l=edges[i].l;
		if(l!=fas[x][0]) Sum(l);
	}
}
void init(){
	dfs(1,0);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=18;j++)
			fas[i][j]=fas[fas[i][j-1]][j-1];
	Sum(1);
}
int LCA(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=18;i>=0;i--){
		if(dep[x]-(1<<i)<dep[y]) continue;
		x=fas[x][i];
	}
	if(x!=y){
		for(int i=18;i>=0;i--)
			if(fas[x][i]!=fas[y][i]) 
				x=fas[x][i],y=fas[y][i];
		x=fas[x][0];
	}
	return x;
}


int Work1(int x,int y,int d,int an=0){
	int lca=LCA(x,y),qwq=0;
	while(1){
		an+=num[x];
		qwq+=(x==lca);
		x=Kfa(x,d);
		if(dep[x]<dep[lca]) break;
	}
	while(1){
		an+=num[y];
		qwq+=(y==lca);
		y=Kfa(y,d);
		if(dep[y]<dep[lca]) break;
	}
	if(qwq==2) an-=num[lca];
	return an;
}
int Work2(int x,int y,int d,int an=0){
	int lca=LCA(x,y);
	int lenx=dep[x]-dep[lca],leny=dep[y]-dep[lca];
	int a=((int)(lenx/d))*d+d,b=((int)(leny/d))*d+d;
	a=Kfa(x,a),b=Kfa(y,b);
	an+=sum[x][d]-sum[b][d];
	an+=sum[y][d]-sum[a][d];
	if(Kfa(x,((int)(lenx/d))*d)==lca) an-=num[lca];
	return an;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n;int f,l;bl=sqrt(n);
	for(int i=1;i<=n;i++) cin>>num[i];
	for(int i=1;i<n;i++){
		cin>>f>>l;
		add_edge(f,l);add_edge(l,f);
	}
	init();
	for(int i=1;i<=n;i++) cin>>que[i];
	for(int i=1;i<n;i++) cin>>len[i];
	for(int i=1;i<n;i++){
		if(len[i]>=bl) cout<<Work1(que[i],que[i+1],len[i])<<endl;
		else cout<<Work2(que[i],que[i+1],len[i])<<endl;
	}
	return 0;
}
2024/9/10 21:44
加载中...