zoukankan      html  css  js  c++  java
  • 线性基+线段树

    线性基+线段树

    XOR 计蒜客

    t组数据,n个数的序列,q次查询,取l,r区间中的数,使得这些数异或后 或 (|)上k的最大值。

    因为最后要 或 上 k,在二进制中,k为1的位置,最后结果也会是1,所以取数的时候,要a[i] & (~k),把一些位置的1消掉。再求最大异或。

    举个例子:k = 8,a[] = {6(110), 10(1010)},如果直接求最大异或 | k,答案是12;如果进行a[i]&(~k)消掉一些1,答案是14;

    用线段树维护。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    struct tree
    {
        LL l, r;
        LL d[70];
    }t[40010];
    LL a[10010], k;
    void built(LL l, LL r, LL x) {
        t[x].l = l, t[x].r = r;
        if(l == r) {
            memset(t[x].d, 0, sizeof(t[x].d));
            LL b = a[l] & (~k);
            for(LL i = 60; i >= 0; i--) {
                if(b & (1LL << i)) {
                    if(t[x].d[i]) b ^= t[x].d[i];
                    else {
                        t[x].d[i] = b;
                        break;
                    }
                }
            }
            return ;
        }
        LL mid = (l + r) / 2;
        built(l, mid, x*2);
        built(mid + 1, r, x*2+1);
        for(LL j = 60; j >= 0; j--) {
            if(t[x*2].d[j]) {
                LL b = t[x*2].d[j];
                for(LL i = 60; i >= 0; i--) {
                    if(b & (1LL << i)) {
                        if(t[x].d[i]) b ^= t[x].d[i];
                        else {
                            t[x].d[i] = b;
                            break;
                        }
                    }
                }
            }
            if(t[x*2+1].d[j]) {
                LL b = t[x*2+1].d[j];
                for(LL i = 60; i >= 0; i--) {
                    if(b & (1LL << i)) {
                        if(t[x].d[i]) b ^= t[x].d[i];
                        else {
                            t[x].d[i] = b;
                            break;
                        }
                    }
                }
            }
        }
    }
    LL ans[70];
    void ask(LL l, LL r, LL x) {
        if(l <= t[x].l && t[x].r <= r) {
            for(LL j = 60; j >= 0; j--) {
                LL b = t[x].d[j];
                if(b) {
                    for(LL i = 60; i >= 0; i--) {
                        if(b & (1LL << i)) {
                            if(ans[i]) b ^= ans[i];
                            else {
                                ans[i] = b;
                                break;
                            }
                        }
                    }
                }
            }
            return ;
        }
        LL mid = (t[x].l + t[x].r) / 2;
        if(l <= mid) ask(l, r, x*2);
        if(r > mid) ask(l, r, x*2+1);
    }
    int main() {
        int t;
        scanf("%d", &t);
        while(t--) {
            LL n, q;
            scanf("%lld %lld %lld", &n, &q, &k);
            for(LL i = 1; i <= n; i++) {
                scanf("%lld", &a[i]);
            }
            built(1, n, 1);
            while(q--) {
                LL l, r;
                scanf("%lld %lld", &l, &r);
                memset(ans, 0, sizeof(ans));
                ask(l, r, 1);
                LL sum = 0;
                for(LL i = 60; i >= 0; i--) {
                    if((sum ^ ans[i]) > sum) sum ^= ans[i];
                }
                printf("%lld
    ", sum | k);
            }
        }
        return 0;
    }
    

    Operation HDU 6579

    t组数据,n个数的序列,m次操作,操作1:0 l r,询问[l,r]最大异或。操作2:1 x 在序列最后面加入x

    看这个大佬的博客吧https://www.cnblogs.com/KirinSB/p/11248546.html

    #include <cstdio>
    #include <cstring>
    int d[35], nd[1000010][35], mpos[1000010][35], pos[35];
    void add(int x, int r) {
        int rr = r;
        for(int i = 31; i >= 0; i--) {
            if(x & (1 << i)) {
                if(d[i]) {
                    if(pos[i] < r) {
                        int tmp = pos[i];
                        pos[i] = r;
                        r = tmp;
                        tmp = x;
                        x = d[i];
                        d[i] = tmp;
                    }
                    x ^= d[i];
                }
                else {
                    d[i] = x;
                    pos[i] = r;
                    break;
                }
            }
        }
        for(int i = 31; i >= 0; i--) {
            nd[rr][i] = d[i];
            mpos[rr][i] = pos[i];
        }
    }
    int ask(int l, int r) {
        int ret = 0;
        for(int i = 31; i >= 0; i--) {
            if(mpos[r][i] >= l) {
                if((ret ^ nd[r][i]) > ret) ret ^= nd[r][i];
            }
        }
        return ret;
    }
    int main() {
        int t;
        scanf("%d", &t);
        while(t--) {
            memset(d, 0, sizeof(d));
            memset(pos, 0, sizeof(pos));
            int n, m, a;
            scanf("%d %d", &n, &m);
            for(int i = 1; i <= n; i++) {
                scanf("%d", &a);
                add(a, i);
            }
            int last = 0;
            while(m--) {
                int op, l, r;
                scanf("%d", &op);
                if(op == 0) {
                    scanf("%d %d", &l, &r);
                    l = (l ^ last) % n + 1;
                    r = (r ^ last) % n + 1;
                    if(l > r) {
                        int tmp = l;
                        l = r;
                        r = tmp;
                    }
                    last = ask(l, r);
                    printf("%d
    ", last);
                }
                else {
                    scanf("%d", &a);
                    a ^= last;
                    n++;
                    add(a, n);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Mac卸载vue-cli2X 时失败: Missing write access to --如侦探小说般的解谜之路
    mac-coursera网站DNS污染的解决方案
    mac摄像头打不开的问题
    node-npm-webpack
    webpack报错 : Can't resolve '.distundle.js'
    npm Error: listen EADDRINUSE 127.0.0.1:8080
    常用mac终端命令
    mac下的环境变量配置- cnpm :command not found
    less安装 出错问题
    vue-devtools vue开发调试神器
  • 原文地址:https://www.cnblogs.com/fanshhh/p/12609141.html
Copyright © 2011-2022 走看看