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;
    }
    
  • 相关阅读:
    Contract
    VS.NET 发布 常识
    案例分析:培训合同与赔款事宜
    DNN最新资源,目前在学SAP,所以.Net的工作就停滞了。
    劳动争议处理依据劳动法
    开发网格应用程序<1>
    BI在中国成了装饰品
    VOIP侵蚀电信利益,未来最赚钱的行业.
    [转]个人知识管理-Web2.0技术下的一个热点
    [转]冲杯三鹿奶粉给你喝!
  • 原文地址:https://www.cnblogs.com/whisperlzw/p/11243293.html
Copyright © 2011-2022 走看看