問題を解決P3292 [[SCOI2016]ラッキーナンバー]

トピックリンク

ソリューション[SCOI2016]ラッキーナンバー

タイトル効果:木、各クエリ独占的権利または最大のポイント与えられたパスに

分析:

ほぼ最大排他的論理和値のサブセットが、我々は従来の線形グループの考えることができる一連の要件を参照してください。

合わせた最初のグループは、線形複雑である\(O(関数logm ^ 2) \) A、\(Mの\)の範囲であります

だから、sbzcyは断面TLEツリーを書きました

我々は変更せずに、静的な課題であることから、最適化を検討する必要があり、我々は同様の要求を検討し\(LCA \)法、乗算マージするパス上の線形グループを

処理に注意してください、そして国境を発行し、多くの場合、わずかなカードを読み取る最適化するために使用します

#include <cstdio>
#include <cctype>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 32769,limit = 62,maxdep = 23;
inline ll read(){
    ll x = 0;char c = getchar();
    while(!isdigit(c))c = getchar();
    while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    return x;
}
struct LB{//线性基
    ll p[limit + 1];
    inline ll query()const{
        ll res = 0;
        for(int i = limit;i >= 0;i--)
            if((res ^ p[i]) > res)res ^= p[i];
        return res;
    }
    inline void insert(ll x){
        for(int i = limit;i >= 0;i--){
            if(!(x >> i))continue;
            if(!p[i]){
                p[i] = x;
                break;
            }
            x ^= p[i];
        }
    }
    inline void merge(const LB &x){
        for(int i = limit;i >= 0;i--)
            if(x.p[i])insert(x.p[i]);
    }
}f[maxn][maxdep + 1],zero;
vector<int> G[maxn];
inline void addedge(int from,int to){
    G[from].push_back(to);
}
int n,q,faz[maxn][maxdep + 1],dep[maxn];
ll val[maxn];
void dfs(int u){//预处理倍增
    dep[1] = 1;
    f[u][0].insert(val[u]);
    for(int i = 1;i <= maxdep;i++)
        f[u][i] = f[u][i - 1],f[u][i].merge(f[faz[u][i - 1]][i - 1]),faz[u][i] = faz[faz[u][i - 1]][i - 1];
    for(int v : G[u]){
        if(v == faz[u][0])continue;
        faz[v][0] = u;
        dep[v] = dep[u] + 1;
        dfs(v);
    }
}
inline ll path_query(int x,int y){//查询
    LB res = zero;
    if(dep[x] < dep[y])swap(x,y);
    for(int i = maxdep;i >= 0;i--)
        if(dep[faz[x][i]] >= dep[y])
            res.merge(f[x][i]),x = faz[x][i];
    if(x == y)return res.merge(f[x][0]),res.query();
    for(int i = maxdep;i >= 0;i--)
        if(faz[x][i] != faz[y][i]){
            res.merge(f[x][i]),x = faz[x][i];
            res.merge(f[y][i]),y = faz[y][i];
        }
    res.merge(f[x][0]);
    res.merge(f[y][0]);
    res.merge(f[faz[x][0]][0]);
    return res.query();
}
int main(){
    n = read(),q = read();
    for(int i = 1;i <= n;i++)val[i] = read();
    for(int x,y,i = 1;i < n;i++)
        x = read(),y = read(),addedge(x,y),addedge(y,x);
    dfs(1);
    for(int x,y,i = 1;i <= q;i++)
        x = read(),y = read(),printf("%lld\n",path_query(x,y));
    return 0;
}

おすすめ

転載: www.cnblogs.com/colazcy/p/11515173.html