老瞎眼 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; }