zoukankan      html  css  js  c++  java
  • Operation HDU

    Operation (HDU - 6579)

    番外:

    初学线性基,推荐一篇线性基学习笔记

    线性基就是一个两两元素异或没有冗余的元素集合。

    我们在集合内每一位记录一个贡献当前位的数字,就可以查询区间异或极值。

    题意:

    给一个初始序列,要求支持两种操作:

    • 查询一个区间内的元素异或最大值。
    • 向序列尾部添加一个元素。

    题解:

    我们考虑做一个前缀线性基和,然后插入元素的同时记录坐标,来保证让贡献高位的元素尽量靠右。这样可以保证在每个线性基和里查询区间的时候,查询到的数尽量大(贡献的位置尽量高)。查询的时候只查询坐标大于等于L的就可以了。

    #include <bits/stdc++.h>
    #define fopi freopen("in.txt", "r", stdin)
    #define fopo freopen("out.txt", "w", stdout)
    using namespace std;
    typedef long long LL;
    const int maxn = 1e6 + 5;
    typedef pair<int, int> Pair;
    
    struct LinearBasis{
        #define N 30
        Pair a[N+1];
    
        void init() {
            memset(a, 0, sizeof(a));
        }
    
        bool insert(int val, int pos) {
            for (int i = N; i >= 0; i--) if (val & (1ll << i)) {
                if (a[i].first == 0) {
                    a[i].first = val;
                    a[i].second = pos;
                    break;
                }
                else if (a[i].second < pos) {
                    swap(val, a[i].first);
                    swap(pos, a[i].second);
                }
                val ^= a[i].first;
            }
            return val > 0;
        }
    
        int query_Max(int l) {
            int res = 0;
            for (int i = N; i >= 0; i--)
                if ((res^a[i].first) > res && a[i].second >= l)
                    res ^= a[i].first;
            return res;
        }
    }LB[maxn];
    
    int T, n, m;
    LL x;
    
    int main() {
    
        //fopi;
    
        scanf("%d", &T);
        for (int ca = 1; ca <= T; ca++) {
            LB[0].init();
    
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++) {
                scanf("%lld", &x);
                LB[i] = LB[i-1];
                LB[i].insert(x, i);
            }
    
            int ans = 0;
            for (int i = 1; i <= m; i++) {
                int op, x, y;
                scanf("%d%d", &op, &x);
                if (op == 0) {
                    scanf("%d", &y);
                    x = (x^ans) % n + 1, y = (y^ans) % n + 1;
                    if (x > y) swap(x, y);
                    printf("%d
    ", ans = LB[y].query_Max(x));
                }
                else {
                    ++n;
                    LB[n] = LB[n-1];
                    LB[n].insert(x^ans, n);
                }
            }
        }
    }
    
    
  • 相关阅读:
    PS_0005:画带颜色在线条框 按住Alt键复制
    零钱兑换(动态规划)
    倒排索引原理和实现
    集群搭建
    java内部类
    nohup &后台运行脚本
    scala构造函数
    spark数据源读取及读数据原理
    安装redis解决公司linux环境的坑
    61、对于employees表中,给出奇数行的first_name
  • 原文地址:https://www.cnblogs.com/ruthank/p/11354434.html
Copyright © 2011-2022 走看看