传送门
题意:
给出一个长度为 n n n的数组,有 q q q次查询,每次查询给出一个区间 [ l , r ] [l,r] [l,r] , 求区间内一些数异或和的最大值。
题解:
求异或和最大,可以想到线性基,那么怎么求区间内异或最大呢?
考虑给每个前缀维护一个线性基,对于一个新加进来的数,我们跟普通的线性基一样去处理它,但其中还要做一点改变。
设 p r e [ i ] [ j ] pre[i][j] pre[i][j] 表示前 i i i 个数组成的线性基中,第 j j j 位的数在数组中的位置,那么我们就需要尽量让 p r e [ i ] [ j ] pre[i][j] pre[i][j] 尽可能的大,即尽可能的往后,那么在查询的时候,只需要看 p r e [ i ] [ j ] ≥ l pre[i][j] geq l pre[i][j]≥l的位置即可,同时也保证了不会漏掉某个情况。
那么在插入新的数时,我们只需判断当前下标是否大于 p r e [ i ] [ j ] pre[i][j] pre[i][j] ,然后交换这两个数即可。
代码:
#pragma GCC diagnostic error "-std=c++11"
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
const int MAXN = 5e5 + 5;
const int inf = 0x3f3f3f3f;
int pre[MAXN][31];
int dp[MAXN][31];
int a[MAXN];
struct node {int l, r;/* data */
} f[MAXN];
bool cmp(node x, node y)
{return x.r < y.r;
}
void insert(int x, int id)
{for (int i = 30; i >= 0; i--)pre[id][i] = pre[id - 1][i], dp[id][i] = dp[id - 1][i];int temp = id;for (int i = 30; i >= 0; i--) {if ((1 << i) & x) {if (!pre[id][i]) {pre[id][i] = temp;dp[id][i] = x;break;} else {if (temp > pre[id][i]) {swap(x, dp[id][i]);swap(temp, pre[id][i]);}x ^= dp[id][i];}}}
}
int main()
{int n;scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);}int q;scanf("%d", &q);for (int i = 1; i <= q; i++) {scanf("%d%d", &f[i].l, &f[i].r);}//sort(f + 1, f + 1 + q, cmp);for (int i = 1; i <= n; i++) {insert(a[i], i);}for (int i = 1; i <= q; i++) {int ans = 0;for (int j = 30; j >= 0; j--) {if (pre[f[i].r][j] >= f[i].l) {if ((ans ^ dp[f[i].r][j]) > ans) {ans ^= dp[f[i].r][j];}}}printf("%dn", ans);}
}
本文发布于:2024-02-02 22:34:10,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170688445046883.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |