列表

详情


NC51147. Fotile 模拟赛L

描述

FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和。
即对于一个询问,你需要求出max(Ai xor A[i+1] xor A[i+2] … xor Aj),其中
为了体现在线操作,对于一个询问(x,y):


其中lastans是上次询问的答案,一开始为0。

输入描述

第一行两个整数N和M。
第二行有N个正整数,其中第i个数为A_i
后M行每行两个整数x,y表示一对询问。

输出描述

共M行,每行输出一个正整数,第i行的正整数表示第i个询问的结果。

示例1

输入:

3 3
1 4 3
0 1
0 1
4 3

输出:

5
7
7

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 501ms, 内存消耗: 7268K, 提交时间: 2020-05-04 22:03:57

//Author:XuHt
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 12006;
int n, m, a[N], ed[N], trie[N*32][2], pos[N*32], f[86][N], tot = 0;

void add(int pre, int now, int num) {
	int p = ed[num] = ++tot;
	pos[p] = num;
	for (int i = 30; i >= 0; i--) {
		int j = (now >> i) & 1;
		trie[p][j^1] = trie[pre][j^1];
		p = trie[p][j] = ++tot;
		pos[p] = num;
		pre = trie[pre][j];
	}
}

int ask(int len, int r, int x) {
	int ans = 0, p = ed[r];
	for (int i = 30; i >= 0; i--) {
		int j = ((x >> i) & 1) ^ 1;
		if (pos[trie[p][j]] >= len) ans |= 1 << i;
		else j ^= 1;
		p = trie[p][j];
	}
	return ans;
}

int main() {
	memset(pos, -1, sizeof(pos));
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		a[i] ^= a[i-1];
	}
	int t = sqrt(m), len = n / t;
	if (n % t) ++len;
	add(0, 0, 0);
	for (int i = 1; i <= n; i++) add(ed[i-1], a[i], i);
	for (int i = 0; i < t; i++)
		for (int j = i * len + 1; j <= n; j++)
			f[i][j] = max(f[i][j-1], ask(i * len, j - 1, a[j]));
	int ans = 0;
	for (int i = 1; i <= m; i++) {
		int x, y;
		scanf("%d %d", &x, &y);
		x = (x + ans) % n + 1;
		y = (y + ans) % n + 1;
		if (x > y) swap(x, y);
		int p = --x / len;
		if (x % len) ++p;
		ans = p * len < y ? f[p][y] : 0;
		p = min(p * len, y);
		for (int j = x; j <= p; j++)
			ans = max(ans, ask(x, y, a[j]));
		printf("%d\n", ans);
		ans %= n;
	}
	return 0;
}

上一题