zoukankan      html  css  js  c++  java
  • 2019杭电多校第一场hdu6579 Operation(线性基)

    Operation

    题目传送门

    解题思路

    把右边的数尽量往高位放,构造线性基的时候同时记录其在原序列中的位置,在可以插入的时候如果那个位置上存在的数字的位置比新放入的要小,就把旧的往后挤。用这种发现构造前缀线性基,求最大前缀和的时候只有忽略位置比l小的即可。

    代码如下

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    
    inline int read(){
        int res = 0, w = 0; char ch = 0;
        while(!isdigit(ch)){
            w |= ch == '-', ch = getchar();
        }
        while(isdigit(ch)){
            res = (res << 3) + (res << 1) + (ch ^ 48);
            ch = getchar();
        }
        return w ? -res : res;
    }
    
    const int N = 1000005;
    
    int a[N];
    int b[N][40], pos[N][40];
    
    void insert(int k, int x)
    {
        for(int i = 30; i >= 0; i --){
            b[k][i] = b[k - 1][i];
            pos[k][i] = pos[k - 1][i];
        }
        int t = k;
        for(int i = 30; i >= 0; i --){
            if((x >> i) & 1){
                if(b[t][i]){
                    if(pos[t][i] < k){
                        swap(b[t][i], x);
                        swap(pos[t][i], k);
                    }
                    x ^= b[t][i];
                }
                else {
                    b[t][i] = x;
                    pos[t][i] = k;
                    break;
                }
            }
        }
    }
    
    int query(int l, int r)
    {
        int ans = 0;
        for(int i = 30; i >= 0; i --){
            if(pos[r][i] >= l){
                if((ans ^ b[r][i]) > ans)
                    ans ^= b[r][i];
            }
        }
        return ans;
    }
    
    int main()
    {
        int T;
        cin >> T;
        while(T --){
            int n, m;
            n = read(), m = read();
            for(int i = 1; i <= n; i ++){
                a[i] = read();
                insert(i, a[i]);
            }  
            int last = 0;
            for(int i = 1; i <= m; i ++){
                int opt;
                opt = read();
                if(opt == 0){
                    int l, r;
                    l = read(), r = read();
                    l = (l ^ last) % n + 1;
                    r = (r ^ last) % n + 1;
                    if(l > r)
                        swap(l, r);
                    last = query(l, r);
                    printf("%d
    ", last);
                }
                else {
                    int x = read();
                    ++n;
                    insert(n, x ^ last);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    数据库事务的四大特性以及事务的隔离级别
    informer使用示例
    Linux内存、Swap、Cache、Buffer详细解析
    浏览器访问百度的整个过程
    安装zookeeper
    配置java环境
    promethues开发
    go mod常用操作说明
    redis使用基础
    channel的声明和使用
  • 原文地址:https://www.cnblogs.com/whisperlzw/p/11243293.html
Copyright © 2011-2022 走看看