老瞎眼 pk 小鲜肉
利用异或前缀和,离线处理。
我们定义为值为
的异或前缀和最后一次出现在
上。
我们通过枚举有区间,然后把异或相同的区间长度存在
上,
之后我们只要在区间查询区间最小值即为答案了。
#include <bits/stdc++.h>
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1
using namespace std;
typedef pair<int, int> pii;
const int N = 2e6 + 10, inf = 0x3f3f3f3f;
int tree[N], a[N], pos[N], ans[N], n, m;
vector<pii> query[N];
void build(int rt, int l, int r) {
if (l == r) {
tree[rt] = inf;
return ;
}
build(lson);
build(rson);
tree[rt] = min(tree[ls], tree[rs]);
}
int query_min(int rt, int l, int r, int L, int R) {
if (l >= L && r <= R) {
return tree[rt];
}
int ans = inf;
if (L <= mid) ans = query_min(lson, L, R);
if (R > mid) ans = min(ans, query_min(rson, L, R));
return ans;
}
void update(int rt, int l, int r, int L, int R, int value) {
if (l >= L && r <= R) {
tree[rt] = value;
return ;
}
if (L <= mid) update(lson, L, R, value);
if (R > mid) update(rson, L, R, value);
tree[rt] = min(tree[ls], tree[rs]);
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
a[i] = a[i - 1] ^ x;
}
for (int i = 1; i <= m; i++) {
int l, r;
scanf("%d %d", &l, &r);
query[r].push_back(make_pair(l, i));
}
build(1, 1, n);
for (int i = 1; i <= n; i++) {
pos[a[i - 1]] = i;
int pre = pos[a[i]];
if (pre) {
update(1, 1, n, pre, pre, i - pre + 1);
}
for (auto it : query[i]) {
ans[it.second] = query_min(1, 1, n, it.first, i);
}
}
for (int i = 1; i <= m; i++) {
printf("%d\n", ans[i] == inf ? -1 : ans[i]);
}
return 0;
} 
京公网安备 11010502036488号