是这周的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;
}