CF 365 div2 D
http://codeforces.com/contest/703/problem/D
题目大意:给你一个长度为n数组,有q个询问,每次询问一个区间[l,r],这个区间的val就是所有数值为偶数个的数的亦或值。
思路:先求出所有区间的亦或和的val,然后利用树状数组离线维护,然后用所有区间^树状数组的亦或区间就是我们所要求的区间。
原因,因为树状数组维护的区间里面保存的是奇的,所以亦或以后就是偶的了
//看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespace std; #define LL long long #define ALL(a) a.begin(), a.end() #define pb push_back #define mk make_pair #define fi first #define se second const int maxn = 1e6 + 5; vector<pair<int, int> > v[maxn]; map<int, int> m; int a[maxn], sum[maxn], tree[maxn], ans[maxn]; int n, q; inline int lowbit(int i) {return i & -i;} void add(int pos, int val){ for (int i = pos; i <= n; i += lowbit(i)){ tree[i] ^= val; } } inline int cal(int pos){ int res = 0; for (int i = pos; i >= 1; i -= lowbit(i)) res ^= tree[i]; return res; } int main(){ scanf("%d", &n); for (int i = 1; i <= n; i++){ scanf("%d", a + i); sum[i] = sum[i - 1] ^ a[i]; } scanf("%d", &q); for (int i = 1; i <= q; i++){ int l, r; scanf("%d%d", &l, &r); v[r].pb(mk(l, i)); } int cnt = 0; for (int i = 1; i <= n; i++){ if (m[a[i]]) add(m[a[i]], a[i]); add(i, a[i]); m[a[i]] = i; int len = v[i].size(); for (int j = 0; j < len; j++){ pair<int, int> p = v[i][j]; int res = sum[i] ^ sum[p.first - 1]; ///printf("i = %d\n", i); int tmp = cal(i) ^ cal(p.first - 1); ans[p.second] = res ^ tmp; if (p.first == 0 && p.second == 0) continue; cnt++; if (cnt == q) break; } } for (int i = 1; i <= q; i++) printf("%d\n", ans[i]); return 0; }
复杂度O(n*log)