zoukankan      html  css  js  c++  java
  • 杭电多校HDU 6579 Operation (线性基 区间最大)题解

    题意:

    强制在线,求(LR)区间最大子集异或和

    思路:

    求线性基的时候,记录一个(pos[i])表示某个(d[i])是在某个位置更新进入的。如果插入时(d[i])(pos[i])小于我当前插入的(pos[r]),那么就用当前插入的数换出原来的(d[i]),继续进行插入并更新(pos),这样就能保证所有的异或和都没有丢失。这样我们只要每次保存出所有(dn[r][maxn])表示最右边为(r)时的线性基就可以直接求出所有区间([L,R])(1 <= L <= R <= r)。只需要满足(pos[i] >= L),当前找的线性基就是可以使用的线性基。

    参考:

    线性基 详细整理

    代码:

    #include<map>
    #include<set>
    #include<cmath>
    #include<cstdio>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxn = 1e6 + 5;
    const int INF = 0x3f3f3f3f;
    const ll MOD = 1e9 + 7;
    struct Liner_Basis{
        int d[32], nd[maxn][32];
        int pos[32], npos[maxn][32];
        int tot;
        void init(){
            memset(d, 0, sizeof(d));
            tot = 0;
        }
        void insert(int x, int r){
            int R = r;
            for(int i = 31; i >= 0; i--){
                if(x & (1LL << i)){
                    if(!d[i]){
                        d[i] = x;
                        pos[i] = r;
                        break;
                    }
                    else if(pos[i] < r){    //把贡献早的换出
                        swap(pos[i], r);
                        swap(d[i], x);
                    }
                    x ^= d[i];  //原来的继续去贡献低位
                }
            }
            for(int i = 31; i >= 0; i--){  //保存当前线性基
                nd[R][i] = d[i];
                npos[R][i] = pos[i];
            }
        }
    
        int getMax(int l, int r){
            int ret = 0;
            for(int i = 31; i >= 0; i--){
                if(npos[r][i] >= l){
                    ret = max(ret, ret ^ nd[r][i]);
                }
            }
            return ret;
        }
    
    }lb;
    int main(){
        int n, m;
        int T;
        scanf("%d", &T);
        while(T--){
           scanf("%d%d", &n, &m);
            lb.init();
            for(int i = 1; i <= n; i++){
                int c;
                scanf("%d", &c);
                lb.insert(c, 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) swap(l, r);
                    last = lb.getMax(l, r);
                    printf("%d
    ", last);
                }
                else{
                    scanf("%d", &l);
                    l = l ^ last;
                    lb.insert(l, ++n);
                }
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    ssh 代理详细解释
    c++ extern c
    php 删除换行符
    doxygen 模板
    php 判断字符串
    php 链接 mysql 数据库
    远程桌面管理:tsmmc.msc在xp系统中的使用
    更改Server 2008域用户密码策略
    Windows Server 2008 IIS7部署
    iis6中FTP配置的技巧和细节
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11248546.html
Copyright © 2011-2022 走看看