首页 > 代码库 > (字典树3道水题)codeforces 665E&282E&514C

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

665E

题意:

给一个数列和一个整数k,求这个数列中异或起来大于等于k的子串数量。

分析:

其实只要维护一个维护前缀和就行了,把前缀和加到字典树里,然后递归search一下,注意需要剪枝,不然会T, 

if(s + (1ll << (i + 1)) - 1 < k)return 0; 

这句话的意思是如果后面的二进制全都是1,都达不到k,就不用继续递归了。

代码:

 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <vector> 6  7  8 using namespace std; 9 10 typedef long long ll;11 12 const int inf = 0x3f3f3f3f;13 const int maxn = 30000010;14 15 16 const int cha = 2;17 const int MAXBITS = 30;18 struct Trie_node {19     ll cnt;20     int nxt[cha];21 } tree[maxn];22 23 int nxt;24 25 int newnode() {26     memset(&tree[nxt], 0, sizeof(Trie_node));27     return nxt++;28 }29 30 void Trie_insert(int val) {31     int rt = 0;32     for(int i = MAXBITS; i >= 0; i--) {33         int id = (val & (1ll << i)) > 0;34         if(!tree[rt].nxt[id]) {35             tree[rt].nxt[id] = newnode();36         }37         rt = tree[rt].nxt[id];38         tree[rt].cnt++;39     }40 }41 42 43 void init() {44     nxt = 1;45     memset(tree, 0, sizeof(tree));46 }47 48 int n;49 long long k;50 51 52 53 ll  Search(int val, int i, ll s, int rt) {54     if(s >= k)return tree[rt].cnt;55     if(s + (1ll << (i + 1)) - 1 < k)return 0;56     if(i < 0)return 0;57     int id = (val & (1ll << i)) > 0;58     ll sum = 0;59     if(tree[rt].nxt[id])sum += Search(val, i - 1, s, tree[rt].nxt[id]);60     if(tree[rt].nxt[id ^ 1])sum += Search(val, i - 1, s + (1ll << i), tree[rt].nxt[id ^ 1]);61     return sum;62 }63 64 int main() {65     scanf("%d%I64d", &n, &k);66     init();67     Trie_insert(0);68     int pre = 0;69     int x;70     ll ans = 0;71     for(int i = 0; i < n; i++) {72         scanf("%d", &x);73         pre ^= x;74         ans += Search(pre, MAXBITS, 0, 0);75         Trie_insert(pre);76     }77     printf("%I64d\n", ans);78     return 0;79 80 }

282E

题意:

找到最大不相交前缀和后缀的异或和。

分析:

同样是维护前缀和,然后动态计算后缀和,在前缀和里找,不断更新ans为max就行了。

代码:

  1 #include <set>  2 #include <map>  3 #include <list>  4 #include <cmath>  5 #include <queue>  6 #include <vector>  7 #include <bitset>  8 #include <string>  9 #include <cctype> 10 #include <cstdio> 11 #include <cstring> 12 #include <cstdlib> 13 #include <iostream> 14 #include <algorithm> 15 #include <ctime> 16  17  18 using namespace std; 19  20 typedef long long ll; 21 typedef unsigned long long ull; 22 #define inf (0x3f3f3f3f) 23 #define lnf (0x3f3f3f3f3f3f3f3f) 24 #define eps (1e-6) 25 int sgn(double a) { 26     return a < -eps ? -1 : a < eps ? 0 : 1; 27 } 28  29 //-------------------------- 30  31 const int maxn = 5000010; 32 const int MAXBITS = 40; 33  34  35 const int cha = 2; 36  37 struct Trie_node { 38     int cnt; 39     int nxt[cha]; 40 } tree[maxn]; 41  42 ll pre[100010]; 43 ll num[100010]; 44  45 int nxt; 46  47 void init() { 48     nxt = 1; 49     memset(tree, 0, sizeof(tree)); 50 } 51  52 int newnode() { 53     memset(&tree[nxt], 0, sizeof(Trie_node)); 54     return nxt++; 55 } 56  57 void Trie_insert(ll val) { 58     int rt = 0; 59     for(int i = MAXBITS; i >= 0; i--) { 60         int id = (val & (1ll << i)) > 0; 61         if(!tree[rt].nxt[id]) { 62             tree[rt].nxt[id] = newnode(); 63         } 64         rt = tree[rt].nxt[id]; 65         tree[rt].cnt++; 66     } 67 } 68  69  70 ll Search(ll val) { 71     int rt = 0; 72     ll res = 0; 73     for(int i = MAXBITS; i >= 0; i--) { 74         int id = (val & (1ll << i)) > 0; 75         if(tree[rt].nxt[id ^ 1]) { 76             res += (1ll << i); 77             rt = tree[rt].nxt[id ^ 1]; 78         } else { 79             rt = tree[rt].nxt[id]; 80         } 81     } 82     return res; 83 } 84  85  86  87 void solve() { 88     int n; 89     cin >> n; 90     init(); 91     pre[0] = 0; 92     for(int i = 1; i <= n; i++) { 93         cin >> num[i]; 94         pre[i] = pre[i - 1] ^ num[i]; 95     } 96  97     ll suf = 0; 98     Trie_insert(0); 99     ll ans = 0;100     for(int i = n; i >= 1; i--) {101         ans = max(ans, Search(pre[i]));102         suf ^= num[i];103         Trie_insert(suf);104     }105     ans = max(ans, Search(0));106     cout << ans << endl;107 }108 109 110 int main() {111     solve();112     return 0;113 }

514C

题意:

给一个字典,判断字符串在字典中是否存在字符串只有一个位置的字符不同。

分析:

这题算是比较简单,只是应该坑点比较多,虽然是1A的。

我的做法是,先进行普通的Trie搜索,一旦发现错的,就进行另一个搜索。

需要处理一些细节的。

代码:

  1 #include <cstdio>  2 #include <cstring>  3 #include <algorithm>  4 #include <iostream>  5 #include <vector>  6   7   8 using namespace std;  9  10 const int inf = 0x3f3f3f3f; 11 const int maxn = 4000010; 12 const int cha = 3; 13  14 struct Trie_node { 15     int cnt; 16     int nxt[cha]; 17     bool exist; 18 } tree[maxn]; 19  20 int nxt; 21  22  23 void init() { 24     nxt = 1; 25     memset(tree, 0, sizeof(tree)); 26 } 27  28  29 int newnode() { 30     memset(&tree[nxt], 0, sizeof(Trie_node)); 31     return nxt++; 32 } 33  34 void Trie_insert(string word) { 35     int rt = 0; 36     int len = word.length(); 37     for(int i = 0; i < len; i++) { 38         int id = word[i] - a; 39         if(!tree[rt].nxt[id]) { 40             tree[rt].nxt[id] = newnode(); 41         } 42         rt = tree[rt].nxt[id]; 43         tree[rt].cnt++; 44     } 45     tree[rt].exist = true; 46 } 47  48 bool _search(int rt, string left) { 49     int len = left.length(); 50     for(int i = 0; i < len; i++) { 51         int id = left[i] - a; 52         if(!tree[rt].nxt[id])return false; 53         rt = tree[rt].nxt[id]; 54     } 55     return tree[rt].exist; 56 } 57  58 bool Trie_search(string word) { 59     int rt = 0; 60     int len = word.length(); 61     for(int i = 0; i < len; i++) { 62         int id =  word[i] - a; 63         if(i == len - 1) { 64             for(int j = 0; j < 3; j++) { 65                 if(id == j)continue; 66                 if(tree[rt].nxt[j] && tree[tree[rt].nxt[j]].exist) return true; 67             } 68             break; 69         } 70         for(int j = 0; j < 3; j++) { 71             if(id == j)continue; 72             if(tree[rt].nxt[j] && _search(tree[rt].nxt[j], word.substr(i + 1, len - i - 1))) { 73                 return true; 74             } 75         } 76         if(!tree[rt].nxt[id])return false; 77         rt = tree[rt].nxt[id]; 78     } 79     return false; 80 } 81  82  83  84 int n, m; 85  86 string str; 87  88 int main() { 89     cin >> n >> m; 90     init(); 91     for(int i = 0; i < n; i++) { 92         cin >> str; 93         Trie_insert(str); 94     } 95     for(int i = 0; i < m; i++) { 96         cin >> str; 97         if(Trie_search(str))puts("YES"); 98         else puts("NO"); 99     }100     return 0;101 102 }

 

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