codeforces 617 E. XOR and Favorite Number(莫队算法)
题目链接:http://codeforces.com/problemset/problem/617/E
题目:
给你a1 a2 a3 ··· an 个数,m次询问:在[L, R] 里面又多少中 [l, r] 使得 al xor al+1 xor ··· ar 为 k。
题解:
本题只有区间查询没有区间修改,而且数据量不大(10w),所以可以用离线的方法解决。
使用莫队算法来解决,就需要O(1)的修改[L, R+1] 、[L, R-1]、[L+1, R]、[L-1, R]。
详细的莫队可以百度学一下。
这里讲一下怎么样通过O(1)来修改
1)我们需要求前缀xor。
2)[L, R] -> [L, R+1]:这里添加了一个aR+1 , 就可以通过前缀xor T,所以我们需要找 T ^ k H 的个数(因为H^T=K-> H=T^K)。
如果H在前面出现过,比如(全部是前缀xor)1 2 1[加入]。这时xor 为1 ,我们当k为0, 那么 0^1 = 1的个数就为1。
这里的1的数量有什么意义。如果我们要想 1 [2 1] 这一段的xor ,是不是应该 T3(1)xor T1(1) = 0 = k;
[L, R] -> [L, R-1] : 这里是删除了一个aR , num[TaR] --, 我们要求的是 k^ TaR 的个数 。
1 2 1 1[删除], k = 0, 0^1 = 1 , 这个有2个1。这里2个的意思 1 [2 1 1] ( T4 xor T1 = 0)和 1 2 1 [1] (T4 xor T3 = 0),因为删去了aR 所以aR 结尾的区间就要减去。
[L, R] -> [L-1, R] : 这个是增加多一个 aL-1 。就是在[L-1, R] 这个里面找 [L-1, r(r<R)] 使得xor 为k , 所以就需要 k^((L-1)-1)。
[L, R] -> [L+1, R] :这里是删除了 aL 。就是在 [L, r(r<R)] 找 xor 为 k 的 。T[r]^T[L-1] = k。
num[0] = 1 。这里是应为一开始前缀异或为0 .
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 #include <cmath> 7 #include <vector> 8 #include <queue> 9 #include <stack> 10 #include <set> 11 using namespace std; 12 typedef long long LL; 13 #define ms(a, b) memset(a, b, sizeof(a)) 14 #define pb push_back 15 #define mp make_pair 16 const int INF = 0x7fffffff; 17 const int inf = 0x3f3f3f3f; 18 const int mod = 1e9+7; 19 const int maxn = 100000+10; 20 int a[maxn]; 21 LL num[3000010]; 22 LL x[maxn]; 23 LL ans[maxn]; 24 struct Point 25 { 26 int l, r, id; 27 }node[maxn]; 28 int unit, n, m, k; 29 void init() { 30 ms(a, 0); 31 ms(ans, 0); 32 ms(num, 0); 33 ms(x, 0); 34 } 35 bool cmp(Point x1, Point x2) 36 { 37 if(x1.l/unit != x2.l/unit){ 38 return x1.l/unit < x2.l/unit; 39 } 40 else 41 return x1.r < x2.r; 42 } 43 void work() 44 { 45 for(int i = 1;i<=n;i++) 46 x[i] = x[i-1]^a[i]; 47 48 int L, R; 49 LL temp = 0; 50 L = 1, R = 0; 51 num[0]++; 52 for(int i = 0;i<m;i++){ 53 while(R<node[i].r){ 54 R++; 55 temp+=num[k^x[R]]; 56 num[x[R]]++; 57 } 58 while(R>node[i].r){ 59 num[x[R]]--; 60 temp-=num[x[R]^k]; 61 R--; 62 } 63 while(L>node[i].l){ 64 L--; 65 temp+=num[k^x[L-1]]; 66 num[x[L-1]]++; 67 } 68 while(L<node[i].l){ 69 num[x[L-1]]--; 70 temp-=num[x[L-1]^k]; 71 L++; 72 } 73 ans[node[i].id] = temp; 74 } 75 } 76 void solve() { 77 scanf("%d%d%d", &n, &m, &k); 78 unit = (int)sqrt(n); 79 for(int i = 1;i<=n;i++) scanf("%d", &a[i]); 80 for(int i = 0;i<m;i++){ 81 node[i].id = i; 82 scanf("%d%d", &node[i].l, &node[i].r); 83 } 84 sort(node, node+m, cmp); 85 work(); 86 for(int i = 0;i<m;i++){ 87 printf("%lld\n", ans[i]); 88 } 89 } 90 int main() { 91 #ifdef LOCAL 92 freopen("input.txt", "r", stdin); 93 // freopen("output.txt", "w", stdout); 94 #endif 95 // ios::sync_with_stdio(0); 96 // cin.tie(0); 97 98 init(); 99 solve(); 100 101 return 0; 102 }