zoukankan      html  css  js  c++  java
  • Luogu 3292 [SCOI2016]幸运数字

    BZOJ 4568。

    感觉很板。

    前置技能:线性基。      放一篇感觉讲的比较丰富的博客: 戳这里

    首先要求在一个序列中任意选点使得异或和最大,当然是想到线性基了。

    把问题转换到树上,如果每次询问的序列是两点之间的路径,也就是说我们只要提取出树上一条路径的线性基就可以了吧。

    发现线性基满足可以快速合并这个性质,如果要合并的话只要把一个暴力插到另一个里面去就行了,这样是两个$log$,我们还可以启发式合并,把小的插到大的里面去,这样会更快。

    所以我们发现可以链剖或者倍增来维护这个东西,我这么懒,当然是倍增了。

    注意倍增的时候是点形成的集合而不是边形成的集合。

    再提两句:

      1、线性基并不满足区间可减性,所以大力可持久化应该是不行的。

      2、点分治可以减少一个$log$,再用$tarjan$求一求$lca$会更快。

    时间复杂度$O(nlog^3n)$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    const int N = 20005;
    const int B = 62;
    const int Lg = 16;
    
    int n, qn, tot = 0, head[N], dep[N], fa[N][Lg];
    ll a[N];
    
    struct Edge {
        int to, nxt;
    } e[N << 1];
    
    inline void add(int from, int to) {
        e[++tot].to = to;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    struct Lp {
        ll p[B]; int cnt;
        
        inline void init() {
            cnt = 0;
            memset(p, 0LL, sizeof(p));
        }
        
        inline void ins(ll val) {
            for(int i = 60; i >= 0; i--) {
                if((val >> i) & 1) {
                    if(!p[i]) {
                        p[i] = val;
                        ++cnt;
                        break;
                    }
                    val ^= p[i];
                }
            }
        }
        
        inline ll getMax() {
            ll res = 0LL;
            for(int i = 60; i >= 0; i--) 
                if((res ^ p[i]) > res) res ^= p[i];
            return res;
        }
        
    } s[N][Lg];
    
    inline Lp merge(Lp u, Lp v) {
        Lp res; res.init();
        if(u.cnt > v.cnt) {
            res = u;
            for(int i = 60; i >= 0; i--) {
                if(!v.p[i]) continue;
                res.ins(v.p[i]);
            }
        } else {
            res = v;
            for(int i = 60; i >= 0; i--) {
                if(!u.p[i]) continue;
                res.ins(u.p[i]);
            }
        }
        return res;
    }
    
    inline void swap(int &x, int &y) {
        int t = x; x = y; y = t;
    }
    
    void dfs(int x, int fat, int depth) {
        fa[x][0] = fat, dep[x] = depth;
        s[x][0].init();
        if(fat) s[x][0].ins(a[fat]);
        for(int i = 1; i <= 15; i++) {
            fa[x][i] = fa[fa[x][i - 1]][i - 1];
            s[x][i] = merge(s[x][i - 1], s[fa[x][i - 1]][i - 1]);
        }
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fat) continue;
            dfs(y, x, depth + 1);
        }
    }
    
    inline Lp getLp(int x, int y) {
        Lp res; res.init();
        res.ins(a[x]), res.ins(a[y]);
        if(dep[x] < dep[y]) swap(x, y);
        for(int i = 15; i >= 0; i--) 
            if(dep[fa[x][i]] >= dep[y]) {
                res = merge(res, s[x][i]);
                x = fa[x][i];
            }
        if(x == y) return res;
        for(int i = 15; i >= 0; i--) 
            if(fa[x][i] != fa[y][i]) {
                res = merge(res, s[x][i]), res = merge(res, s[y][i]);
                x = fa[x][i], y = fa[y][i];
            }
        res = merge(res, s[x][0]), res = merge(res, s[y][0]);
        return res;
    }
    
    inline void solve(int x, int y) {
        Lp res = getLp(x, y);
        printf("%lld
    ", res.getMax());
    }
    
    int main() {
        read(n), read(qn);
        for(int i = 1; i <= n; i++) read(a[i]);
        for(int x, y, i = 1; i < n; i++) {
            read(x), read(y);
            add(x, y), add(y, x);
        }
        
        dfs(1, 0, 1);
        
        for(int x, y; qn--; ) {
            read(x), read(y);
            solve(x, y);
        }
        
        return 0;
    }
    View Code

     唔,Linear Basis居然被我写成了Lp……无话可说

  • 相关阅读:
    day01--计算机硬件基础笔记
    22 Jun 18 Django,ORM
    21 Jun 18 Django,ORM
    20 Jun 18 复习, mysql
    20 Jun 18 Django,ORM
    19 Jun 18 复习, 正则表达式
    19 Jun 18 Django
    15 Jun 18 复习, shutil模块
    15 Jun 18 Django
    14 Jun 18 复习, form表单
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9693522.html
Copyright © 2011-2022 走看看