1. 程式人生 > >codeforces 617 E. XOR and Favorite Number(莫隊算法)

codeforces 617 E. XOR and Favorite Number(莫隊算法)

truct .com src sort while 開始 算法 printf turn

題目鏈接: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 }
View Code

codeforces 617 E. XOR and Favorite Number(莫隊算法)