首页 > 代码库 > (字典树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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。