CF840E In a Trap

发现答案在二进制下最多为 (16) 位,那么将 (v)(u) 的路径每 (256) 个点分为一段,得同一段在二进制下 (dis) 的高 (8) 位相同。

(f_{x,i}) 为从 (x) 向上的一段,高 (8) 位为 (i) 时答案的最大值,询问就暴力跳即可。

#include<bits/stdc++.h>
#define maxn 100010
#define maxm 310
#define S 255
using namespace std;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
int n,q;
int a[maxn],fa[maxn],dep[maxn],f[maxn][maxm],g[maxn];
struct edge
{
    int to,nxt;
}e[maxn];
int head[maxn],edge_cnt;
void add(int from,int to)
{
    e[++edge_cnt]={to,head[from]},head[from]=edge_cnt;
}
void dfs(int x,int fath)
{
    fa[x]=fath,dep[x]=dep[fath]+1;
    for(int i=head[x];i;i=e[i].nxt)
    {
        int y=e[i].to;
        if(y==fath) continue;
        dfs(y,x);
    }
}
void work(int x)
{
    int p=x;
    for(int i=0;i<=S&&p;++i,p=fa[p])
    {
        int v=a[p]>>8;
        f[x][v^S]=max(f[x][v^S],(a[p]^i)|(S<<8));
    }
    g[x]=p;
    for(int j=0;j<8;++j)
        for(int i=0;i<=S;++i)
            if(f[x][i^(1<<j)])
                f[x][i]=max(f[x][i],f[x][i^(1<<j)]^(1<<(j+8)));
}
int main()
{
    read(n),read(q);
    for(int i=1;i<=n;++i) read(a[i]);
    for(int i=1;i<n;++i)
    {
        int x,y;
        read(x),read(y);
        add(x,y),add(y,x);
    }
    dfs(1,0);
    for(int i=1;i<=n;++i) work(i);
    while(q--)
    {
        int x,y,p,ans=0;
        read(x),read(y),p=y;
        for(int i=0;dep[g[p]]>=dep[x]&&p;++i,p=g[p]) ans=max(ans,f[p][i]);
        while(dep[p]>=dep[x]) ans=max(ans,a[p]^(dep[y]-dep[p])),p=fa[p];
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lhm-/p/13922805.html