• SCOI2016幸运数字(树剖/倍增/点分治+线性基)


    题目链接

    loj
    luogu

    题意

    求树上路径最大点权异或和

    自然想到(维护树上路径)+ (维护最大异或和)
    那么有三种方法可以选择
    1.树剖+线性基
    2.倍增+线性基
    3.点分治+线性基

    至于线性基的合并
    一共就是long级的
    暴力合并就好啦

    这是一份在loj T掉在洛谷AC的可怜代码

    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <vector> 
    using namespace std;
    const int N = 2e4 + 2;
    const int LIM = 60;
    
    inline int read()
    {
        int x=0;bool t=false;char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=true,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return t?-x:x;
    }
    
    struct Edge{
        int v, next;
    }edge[N << 1];
    int esize, head[N];
    inline void addedge(int x, int y){
        edge[++esize] = (Edge){y, head[x]};
        head[x] = esize;
    }
    
    struct XXJ{
        long long w[LIM + 2];
        XXJ(){
            memset(w, 0, sizeof(w));
        }
        void ins(long long x){
            for(int i = LIM; ~i; --i){
                if(!(x >> i)) continue;
                else if(!w[i]){w[i] = x; break;}
                x ^= w[i];
            }
        }
        void print(){
            long long res = 0;
            for(int i = LIM; ~i; --i) 
                if((res ^ w[i]) > res) res ^= w[i];
     		printf("%lld
    ", res);
        }
    }px[N][18];
    long long w[N];
    int p[N][18], dep[N];
    int n, m;
    
    XXJ merge(XXJ x, XXJ y){
        for(int i = LIM; i >= 0; --i){
            if(y.w[i]) x.ins(y.w[i]);
        }
        return x;
    }
    
    XXJ LCA(int x, int y){
        XXJ res;
        res.ins(w[x]); res.ins(w[y]);
        if(dep[x] < dep[y]) swap(x, y); 
        for(int i = 15; i >= 0; --i)
            if(dep[x] - (1 << i) >= dep[y]){
            	res = merge(res, px[x][i]);
            	x = p[x][i];
            }
        if(x == y) return res;
        for(int i = 15; i >= 0; --i){
        	if(p[x][i] != p[y][i]){
        		res = merge(res, px[x][i]);
        		res = merge(res, px[y][i]);
        		x = p[x][i], y = p[y][i];
        	}
        }
        res = merge(res, px[x][0]);
        return res;
    }
    
    void dfs(int x, int ff){
        dep[x] = dep[ff] + 1;
        p[x][0] = ff;
        px[x][0].ins(w[ff]); 
        for(int i = head[x], vv; ~i; i = edge[i].next){
            vv = edge[i].v; if(vv == ff) continue;
            dfs(vv, x);
        }
    }
    
    void calc(){
        for(int i = 1; i <= 15; ++i){
            for(int j = 1; j <= n; ++j){
                p[j][i] = p[p[j][i - 1]][i - 1];
                px[j][i] = merge(px[j][i - 1], px[p[j][i - 1]][i - 1]);
            }
        }
    }
     
    int main() {
        memset(head, -1, sizeof(head));
        
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i){
            scanf("%lld", &w[i]);
        } 
        for(int i = 1, x, y; i < n; ++i){
            scanf("%d%d", &x, &y);
            addedge(x, y); addedge(y, x);
        }
        dfs(1, 0); 
        calc();
        for(int i = 1, x, y; i <= m; ++i){
            x = read(), y = read();
            XXJ res = LCA(x, y);
            res.print();
        }
        return 0;
    }  
    
  • 相关阅读:
    double类型的数值计算
    模拟ATM的功能
    自学Java第七周的总结
    自学java第六周的总结
    自学Java第五周的总结
    自学Java第四周的总结
    自学Java第三个星期的总结
    自学Java第二周的总结
    python-----静态方法
    python----类方法
  • 原文地址:https://www.cnblogs.com/hjmmm/p/10433156.html
Copyright © 2020-2023  润新知