Adventure C CF-665E(字典树)

Posted zhang-kelly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Adventure C CF-665E(字典树)相关的知识,希望对你有一定的参考价值。

题意:

给一个序列,问有多少个区间的异或和大于等于$K$。

思路:

处理出前缀异或和。

对于每个区间$(l,r)$的异或和为$sum[l] $^$ sum[r]$。

对于每个$sum[i]$,如果大于$K$,$ans+1$。

在字典树上查询二进制的每一位。

①$sum=1,k=1$:走$next[0]$边。

②$sum=1,k=0$:先$ans+cnt[0]$,再走$next[1]$边。

③$sum=0,k=1$:走$next[1]$边。

④$sum=0,k=0$:先$ans+cnt[1]$,再走$next[0]$边。

如果最后走到底,即表示异或和等于$K$,那么再加上该点的$cnt$。

代码:

  1 //#include<bits/stdc++.h>
  2 #include <set>
  3 #include <map>
  4 #include <stack>
  5 #include <cmath>
  6 #include <queue>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstring>
 11 #include <iostream>
 12 #include <algorithm>
 13 
 14 #define ll long long
 15 #define pll pair<ll,ll>
 16 #define pii pair<int,int>
 17 #define bug printf("*********
")
 18 #define FIN freopen("input.txt","r",stdin);
 19 #define FON freopen("output.txt","w+",stdout);
 20 #define IO ios::sync_with_stdio(false),cin.tie(0)
 21 #define ls root<<1
 22 #define rs root<<1|1
 23 #define pb push_back
 24 
 25 using namespace std;
 26 const int inf = 2e9 + 7;
 27 const ll Inf = 1e18 + 7;
 28 const int maxn = 3e7 + 5;
 29 const int mod = 1e9 + 7;
 30 
 31 struct Trie
 32 {
 33     struct node
 34     {
 35         int next[2];
 36         int cnt;
 37     }p[maxn];
 38     int tot;
 39     
 40     void init()
 41     {
 42         memset(p[0].next, 0, sizeof p[0].next);
 43         p[0].cnt = 0;
 44         tot = 0;
 45     }
 46 
 47     void insert(int s)
 48     {
 49         int now = 0;
 50         for (int i = 30; i >= 0; --i)
 51         {
 52             int x = (s >> i) & 1;
 53             if (!p[now].next[x])
 54             {
 55                 memset(p[++tot].next, 0, sizeof p[tot].next);
 56                 p[tot].cnt = 0;
 57                 p[now].next[x] = tot;
 58             }
 59             now = p[now].next[x];
 60             p[now].cnt++;
 61         }
 62     }
 63 
 64     ll find(int x, int k)
 65     {
 66         int now = 0, i;
 67         ll res = 0;
 68         for (i = 30; i >= 0; --i)
 69         {
 70             int    tmp_x = (x >> i) & 1, tmp_k = (k >> i) & 1;
 71             int pre = now;
 72             if (tmp_x && tmp_k)
 73             {
 74                 if (p[now].next[0])    now = p[now].next[0];
 75             }
 76             else if (tmp_x && !tmp_k)
 77             {
 78                 if (p[now].next[0])    res += p[p[now].next[0]].cnt;
 79                 if (p[now].next[1])    now = p[now].next[1];
 80             }
 81             else if (!tmp_x && tmp_k)
 82             {
 83                 if (p[now].next[1])    now = p[now].next[1];
 84             }
 85             else if (!tmp_x && !tmp_k)
 86             {
 87                 if (p[now].next[1])    res += p[p[now].next[1]].cnt;
 88                 if (p[now].next[0])    now = p[now].next[0];
 89             }    
 90             if (pre == now)    break;
 91         }
 92         if (i == -1)    res += p[now].cnt;
 93         return res;
 94     }
 95 };
 96 
 97 int n, k, sum[maxn];
 98 ll ans = 0;
 99 Trie t;
100 
101 int main()
102 {
103     t.init();
104     scanf("%d %d", &n, &k);
105     for (int i = 1; i <= n; ++i)
106     {
107         scanf("%d", &sum[i]);
108         sum[i] ^= sum[i - 1];
109         if (sum[i] >= k)    ans++;
110         ans += t.find(sum[i], k);
111         t.insert(sum[i]);
112     }
113     printf("%lld
", ans);
114 }

 

以上是关于Adventure C CF-665E(字典树)的主要内容,如果未能解决你的问题,请参考以下文章

(字典树3道水题)codeforces 665E&282E&514C

Trie树-字典树

Codeforces Round #451 Div. 2 C D E

Intelligent IME HDU - 4287 字典树

codeforces 456d (字典树+DP)

什么是字典排序