loj 2013. 「SCOI2016」幸运数字(线性基+lca倍增)

来源:互联网 发布:程序员技术的重要性 编辑:程序博客网 时间:2024/06/07 23:02

题目连接

2013. 「SCOI2016」幸运数字
给一颗树,每个点有一个值ai,求uv路径上异或最大值

分析

涉及异或的东西,就是线性基了,如果你对这玩意不熟,可参考这个Sengxian’s Blog

然后由于线性基合并是log2V 因此,可以暴力合并,也就是采用倍增思想,计算u,v 到公共祖先路径上的线性基,然后合并就行了

Ac code

#include <bits/stdc++.h>using namespace std;#define ms(x,v) (memset((x),(v),sizeof(x)))#define pb push_backtypedef long long LL;const int maxn = 20000+10;const int LOG_MAXN = 15;const int MOD = 998244353;int n,q;const int MAX_BASE = 60;LL a[maxn];struct LinearBase{    LL base[MAX_BASE+1];    LinearBase(){ms(base,0);}    bool insert(LL val){        for(int i=MAX_BASE ; i>=0 ; --i){            if(val >>i &1){                if(base[i])val ^=base[i];                else{base[i]=val ; break;}            }        }        return val>0;    }    LinearBase merge(LinearBase & o) {        for(int i=MAX_BASE ; i>=0 ; --i)if(o.base[i])insert(o.base[i]);return *this;    }    LL max(){        LL ans =0;        for(int i=MAX_BASE ;i>=0 ; --i)ans = std::max(ans,ans ^ base[i]);return ans;    }};LinearBase lb[maxn][LOG_MAXN+1];int dep[maxn],fa[maxn][LOG_MAXN+1];std::vector<int> G[maxn];void dfs(int u,int father) {    dep[u] = dep[father]+1;    fa[u][0]=father;    lb[u][0].insert(a[father]);lb[u][0].insert(a[u]);    // std::cout << " lb " << u <<" " << 0 << " " <<lb[u][0].max() << '\n';    for(int i=1 ; (1<<i)<=dep[u] ; ++i){        fa[u][i] = fa[fa[u][i-1]][i-1];        lb[u][i].merge(lb[u][i-1]);lb[u][i].merge(lb[fa[u][i-1]][i-1]);        //std::cout << " lb " << u <<" " << i << " " <<lb[u][i].max() << '\n';    }    for(auto v : G[u])        if(v!=father)dfs(v,u);}LinearBase lca(int x,int y){    LinearBase ans;    if(dep[x] <dep[y])swap(x,y);    int bin=dep[x]-dep[y];    for(int i=0 ; i<LOG_MAXN ; ++i)        if(bin>>i&1)ans.merge(lb[x][i]),x=fa[x][i];    if(x==y){ans.insert(a[y]);return ans;}    for(int i= LOG_MAXN-1 ; i>=0 ; --i){        if(fa[x][i]!=fa[y][i])ans.merge(lb[x][i]),ans.merge(lb[y][i]),x=fa[x][i],y=fa[y][i];    }    ans.merge(lb[x][0]);ans.insert(a[y]);    return ans;}int main(){    ios_base::sync_with_stdio(0);    cin.tie(0);    cout.tie(0);    cin>>n>>q;    for(int i=1 ; i<=n ; ++i)cin>>a[i];    for(int i=1 ; i<n ; ++i){        int u,v;        cin>>u>>v;        G[u].pb(v);G[v].pb(u);    }    dfs(1,0);    while (q--) {        int x, y;cin>>x>>y;        std::cout << lca(x,y).max() << '\n';    }    return 0;}
阅读全文
0 0