刚学电脑竞赛求调(悬关!)
查看原帖
刚学电脑竞赛求调(悬关!)
247269
MSqwq楼主2023/10/1 21:13

是这周的cf div3 g 你好大佬,我是刚学这个电脑竞赛的萌新,对于这个题,我想的是倍增+枚举,分别让 x 和 y 爬两次,枚举每次爬的那个数要满足的二进制位个数,但是它 wa4 了。
如果你能帮助我,我会给你原石和星穹。
帮帮我,大佬先生! https://codeforces.com/contest/1878/submission/226164800

#include<bits/stdc++.h>
#define int long long
using namespace std;

inline int read()
{
	int x=0,f=1;char 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;
}

const int N=2e5+10,B=20;
vector<int>v[N];
int a[N];
int dep[N],f[N][B],d[N][B],lg[N];

void dfs(int x,int fa)
{
	dep[x]=dep[fa]+1;f[x][0]=fa,d[x][0]=a[x];
	for(int i=1;i<B;i++)
	{
		f[x][i]=f[f[x][i-1]][i-1];
		d[x][i]=d[x][i-1]|d[f[x][i-1]][i-1];
	}
	for(auto to:v[x])if(to!=fa)dfs(to,x);
}

int LCA(int x,int y)
{
	if(dep[x]<dep[y])swap(x,y);
	while(dep[x]>dep[y])x=f[x][lg[dep[x]-dep[y]-1]];
	if(x==y)return x;
	for(int i=lg[dep[x]];i>=0;i--)
		if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
	return f[x][0];
}

void solve()
{
	int n=read();for(int i=1;i<=n;i++)v[i].clear();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read();
		v[x].push_back(y),v[y].push_back(x);
	}
	dfs(1,0);
	int q=read();
	while(q--)
	{
		int x=read(),y=read();int lca=LCA(x,y),ans=0;
		for(int hutao=1;hutao<=2;hutao++)
		{
			swap(x,y);
			int dis=dep[x]-dep[lca]+1;
			for(int i=0;i<32;i++)
			{
				int xx=x,now=0,sum=1;
				for(int j=B-1;j>=0;j--)
				{
					if(__builtin_popcount(now|d[xx][j])>=i)continue;
					now|=d[xx][j],xx=f[xx][j],sum+=1<<j;
				}
				if(sum>dis)continue;
				auto calc=[&](int x,int k)
				{
					int res=0;
					for(int i=0;i<B;i++)
						if(k&(1<<i))res|=d[x][i],x=f[x][i];
					return res;
				};
				int res=calc(xx,dis-sum+1)|calc(y,dep[y]-dep[lca]);
				ans=max(ans,i+__builtin_popcount(res));
			}
		}
		cout<<ans<<" ";
	}
	cout<<endl;
}

signed main()
{
	for(int i=0;i<N;i++)lg[i]=lg[i-1]+(1<<lg[i-1]==i);
	int T=read();
	while(T--)solve();
	return 0;
}
2023/10/1 21:13
加载中...