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
Codeforces Round #451 Div. 2 C D E