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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6579

    题目大意是两个操作,1个是求【l,r】区间子序列的最大异或和,另一个是在最后面添加一个数。

    如果题目简化成求【1,,i】的最大异或和,那么该怎么想呢....

    当然是处理出来一个前缀线性基啦。那么如何求一个区间呢....

    那就处理前缀线性基的时候记录线性基上该位置是在原序列的哪个位置,求值的时候在第r个线性基上找,如果位置>=l则是合法的。

    可是这样想有点怪怪的。

    如果有两个相同的数在同一位那不就不好说了嘛?

    遇到这种情况则用贪心的想法,如果在同一位上明显原序列越大的数越优,因为如果把原序列小的留下,则区间长度较小时明显没有原序列大的数更优,所以贪心的留下原序列大的。

     1 #include <algorithm>
     2 #include<iostream>
     3 #include <cstdio>
     4 #include <vector>
     5 #include <cstring>
     6 #include<queue>
     7 using namespace std;
     8 typedef long long ll;
     9 const int maxn = 5e5 + 3;
    10 int p[maxn][40], pos[maxn][40];
    11 int a[maxn];
    12 void insert(int k, int x) {
    13     for (int i = 0; i <= 30; i++) {
    14         p[k][i] = p[k - 1][i];
    15         pos[k][i] = pos[k - 1][i];
    16     }
    17     int w = k;
    18     for (int i = 30; i >= 0; i--) {
    19         if (x&(1 << i)) {
    20             if (p[k][i] == 0) {
    21                 p[k][i] = x;
    22                 pos[k][i] = w;
    23                 break;
    24             }
    25             else {
    26                 if (w > pos[k][i]) {
    27                     swap(pos[k][i], w);
    28                     swap(p[k][i], x);
    29                 }
    30                 x ^= p[k][i];
    31             }
    32         }
    33     }
    34 }
    35 int main() {
    36     int t;
    37     scanf("%d", &t);
    38     while (t--) {
    39         int n, m;
    40         int ans = 0;
    41         scanf("%d%d", &n, &m);
    42         for (int i = 1; i <= n; i++) {
    43             scanf("%d", &a[i]);
    44             insert(i, a[i]);
    45         }
    46         for (int i = 1; i <= m; i++) {
    47             int opt, x, y;
    48             scanf("%d", &opt);
    49             if (opt) {
    50                 scanf("%d", &x);
    51                 a[++n] = x ^ ans;
    52                 insert(n, a[n]);
    53             }
    54             else {
    55                 scanf("%d%d", &x, &y);
    56                 int l = (x^ans) % n + 1, r = (y^ans) % n + 1;
    57                 if (l > r)
    58                     swap(l, r);
    59                 ans = 0;
    60                 for (int j = 30; j >= 0; j--)
    61                     if ((ans^p[r][j]) > ans && pos[r][j] >= l)ans ^= p[r][j];
    62                 printf("%d
    ", ans);
    63             }
    64 
    65         }
    66     }
    67 }
    View Code
  • 相关阅读:
    Gmail总是把MS发来的信作为垃圾邮件
    添加了CSpreadSheet.h后出现LNK2005错误
    弃用Eudora
    卸载Intel C++ Compiler后Visual C++ 6.0不能工作了
    Matlab对多CPU系统的支持
    Borland决定出售Delphi、JBuilder、C++Builder等IDE产品
    微软提供的免费软件
    生命在于运动?
    "Cannot modify header information"的解决方法
    慢慢的,我们长成了受困于数字的大人
  • 原文地址:https://www.cnblogs.com/sainsist/p/11305450.html
Copyright © 2011-2022 走看看