• 【2017西安邀请赛:A】XOR(线段树+线性基)


    前言:虽然已经有很多题解了,但是还是想按自己的理解写一篇。

    思路:首先分析题目

       一、区间操作 —— 线段树

       二、异或操作 —— 线性基

       这个两个不难想,关键是下一步的技巧

        “或”运算 就是两个数的二进制中,对应位 只要有1,那么就是该位结果就是 1,所以要想k“或”运算后的结果尽量大,

       就需要异或出的数,各个位上的1尽量多。

       线性基的操作,可以求出区间最大异或和,但是我们需要的结果是  “或”运算。

       所以我们可以将 k 取反,然后把所有数在加入线性基之前,全部 “与”运算一遍,再加入线性基。

       这样,线性基中的每一位,全部都是能使得k变大的数了,因为k的二进制上的每一位 1 的位置,线性基中都是0。

       所以,我们只需要求, k 异或 线性基中最大异或和 。

      

    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#pragma GCC optimize(2)
    #include <bits/stdc++.h>
    #include<unordered_set>
    
    using namespace std;
    typedef double dou;
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef map<int, int> mii;
    
    #define pai acos(-1.0)
    #define M 10050
    #define inf 0x3f3f3f3f
    #define mod 1000000007
    #define IN inline
    #define W(a) while(a)
    #define lowbit(a) a&(-a)
    #define left k<<1
    #define right k<<1|1
    #define lson L, mid, left
    #define rson mid + 1, R, right
    #define ms(a,b) memset(a,b,sizeof(a))
    #define Abs(a) (a ^ (a >> 31)) - (a >> 31)
    #define random(a,b) (rand()%(b+1-a)+a)
    #define false_stdio ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    
    int T;
    int n, q, k;
    int tmp, x, y, z;
    
    struct Data {
        int num[35];
        void insert(int t) {
            for (int i = 31; i >= 0; i--) {
                if (t >> i & 1) {
                    if (!num[i]) { num[i] = t; break; }
                    t ^= num[i];
                }
            }
        }
    }tree[M << 2], ans;
    
    IN void Updata(int L, int R, int k,int pos) {
        tree[k].insert(tmp);
        if (L == R)return;
        int mid = L + R >> 1;
        if (pos <= mid)Updata(lson, pos);
        else Updata(rson, pos);
    }
    
    IN void Query(int L, int R, int k) {
        if(x<=L && R<=y){
            for (int i = 31; i >= 0; i--) {
                if (tree[k].num[i])ans.insert(tree[k].num[i]);
            }
            return;
        }
        int mid = L + R >> 1;
        if (x <= mid)Query(lson);
        if (y > mid)Query(rson);
    }
    
    IN int read() {//快读
        int v = 0, f = 0; char ch = getchar();
        W(!isdigit(ch)) { f |= ch == '-'; ch = getchar(); }
        W(isdigit(ch)) { v = (v << 3) + (v << 1) + (ch ^ 48); ch = getchar(); }
        return f ? -v : v;
    }
    
    int main() {
        T = read();
        W(T--) {
            n = read(), q = read(), k = read();
            for (int i = 1; i <= n; i++) {
                tmp = read();
                tmp &= (~k);//关键的一步
                Updata(1, n, 1, i);
            }
            W(q--) {
                ms(ans.num, 0);
                x = read(), y = read();
                Query(1, n, 1);
                z = k;
                for (int i = 31; i >= 0; i--)z = max(z, z ^ ans.num[i]);
                printf("%d
    ", z);
            }
        }
        return 0;
    }

       

       

  • 相关阅读:
    楼宇及工业自动化总线协议介绍
    PROFIBUS,PROFINET,Ethernet三者的区别
    转:OSAL多任务资源分配机制
    Zigbee系列 学习笔记二(工程文件分析)
    Zigbee系列 学习笔记一(协议栈)
    STC12C5A60S2单片机 PWM调试
    单片机 IO口配置模式介绍
    串口通信校验方式
    STC12C5A60S2单片机 串口调试
    本地Nexus 3.3.2 启动
  • 原文地址:https://www.cnblogs.com/caibingxu/p/11788485.html
Copyright © 2020-2023  润新知