• [51nod 1577] 异或凑数


    从左到右一共n个数,数字下标从1到n编号。

    一共m次询问,每次询问是否能从第L个到第R个数中(包括第L个和第R个数)选出一些数使得他们异或为K。

    数据量比较大。

    输入请用快速读入

    输出请用puts

    Input
    单组测试数据。
    第一行一个整数n(0<n<=500,000)。
    第二行n个整数,0<每个数<2^30。
    第三行一个数m,表示询问次数(0<m<=500,000)。
    接下来m行每行三个数,L,R,K(0<L<=R<=n,0<K<2^30)。
    Output
    M行,每行为YES或NO
    Input示例
    5
    1 1 2 4 6
    3
    1 2 1
    2 4 8
    3 5 7
    Output示例
    YES
    NO
    NO




    异或的问题当然是线性基了。
    但是如何维护区间内的线性基呢?
    线段树不太现实, 因为线性基只能暴力合并,再加上线段树就是三个log肯定炸了。
    我们考虑一个以l为左端点的线性基, 并且每一个基存一下它出现的位置。
    从后往前跑, 已经构造了i以后的线性基, 正在插入i。
    如果线性基中他的位置存在一个数,就比较一下这个数的位置和i的大小关系,位置靠前的插入线性基, 位置考后的接着在线性基里跑。
    复杂度O(NlongN)。

     
    #include <iostream>
    #include <cstdio>
    using namespace std;
    #define reg register
    inline int read() {
        int res=0;char ch=getchar();bool flag=0;
        while(!isdigit(ch)) {if(ch=='-')flag=1;ch=getchar();}
        while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48), ch=getchar();
        return flag ? -res : res;
    }
    int n, a[500005];
    struct Lbase {
        int x, id;
    }f[500005][31];
    
    int main()
    {
        n = read();
        for (reg int i = 1 ; i <= n ; i ++) a[i] = read();
        for (reg int i = n ; i >= 1 ; i --)
        {
            memcpy(f[i], f[i+1], sizeof f[i]);
            Lbase now = (Lbase){a[i], i};
            for (reg int j = 30 ; j >= 0 ; j --)
            {
                if (now.x >> j)
                {
                    if (!f[i][j].x) swap(now, f[i][j]);
                    else {
                        if (f[i][j].id > now.id) swap(now, f[i][j]);
                        now.x ^= f[i][j].x;
                    }
                }
            }
        }
        int T = read();
        while(T--)
        {
            int l = read(), r = read();
            int k = read();
            for (reg int i = 30 ; i >= 0 ; i --)
            {
                if ((k >> i) & 1)
                {
                    if (f[l][i].id <= r and f[l][i].x)
                        k ^= f[l][i].x;
                }
            }
            if (!k) puts("Yes");
            else puts("No");
        }
        return 0;
    }
    
    
    


  • 相关阅读:
    python学习day3--python基础
    python学习day2--python基础
    python学习day1--python基础
    包导入原则
    模块搜索路径
    继承顺序
    继承,派生,组合
    面向对象程序设计
    类和对象
    递归
  • 原文地址:https://www.cnblogs.com/BriMon/p/9536452.html
Copyright © 2020-2023  润新知