2019杭电多校第一场 Operation HDU - 6579
Posted smallhester
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019杭电多校第一场 Operation HDU - 6579相关的知识,希望对你有一定的参考价值。
题意:给出一个序列,两种操作,求区间[l,r]的区间最大异或和,和在末尾添加一个数
思路:强制在线,保存每个线性基的数值,接下去直接去搜第r个线性基,但要保持时间比l要大,新增了一个pos数组代表一个数插入时的时间戳,插入的时候如果可以替换那么就用之后的替换之前的,保证线性基中都是最新的元素,可以直接插入即可以直接插入
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<stack> #include<cstdlib> #include<queue> #include<set> #include<string.h> #include<vector> #include<deque> #include<map> using namespace std; #define INF 0x3f3f3f3f3f3f3f3f #define inf 0x3f3f3f3f #define eps 1e-4 #define bug printf("*********\n") #define debug(x) cout<<#x"=["<<x<<"]" <<endl typedef long long LL; typedef long long ll; const int maxn = 1e6 + 5; const int mod = 998244353; int sum[maxn][50],pos[maxn][50]; //sum数组是数字,pos数组是时间,一共有maxn个线性基,sum[i][j]表示第i个线性基 int tot; //时间戳 void add(int num) tot++; for (int i = 0; i < 32; i++) //保留了每个时间的线性基 sum[tot][i] = sum[tot - 1][i]; pos[tot][i] = pos[tot - 1][i]; int now = tot; // 当前时间戳 for (int i = 32; i >= 0; i--) if (num & (1LL << i)) //可以插入就直接插入 if (sum[tot][i] == 0) sum[tot][i] = num; pos[tot][i] = now; break; if (now > pos[tot][i]) //如果当前插入的数之前已经存在过,那么就需要替换 swap(now, pos[tot][i]); swap(num, sum[tot][i]); num ^= sum[tot][i]; int query(int l,int r) //直接访问的是第r个线性基 int ans = 0; for (int i = 32; i >= 0; i--) //当前数的出现的时间戳比l大 if (pos[r][i] >= l) ans = max(ans, ans xor sum[r][i]); return ans; int main() int t; scanf("%d", &t); while (t--) tot = 0; int lastans = 0; int n, m; scanf("%d %d", &n, &m); int num; for (int i = 0; i < n; i++) scanf("%d", &num); add(num); while (m--) int op, l, r; scanf("%d", &op); if (op == 0) scanf("%d %d", &l, &r); l = (l xor lastans) % n + 1; r = (r xor lastans) % n + 1; if (l > r) swap(l, r); lastans = query(l, r); printf("%d\n", lastans); else scanf("%d", &r); add(r xor lastans); n++;
以上是关于2019杭电多校第一场 Operation HDU - 6579的主要内容,如果未能解决你的问题,请参考以下文章