1. 程式人生 > >(字典樹3道水題)codeforces 665E&282E&514C

(字典樹3道水題)codeforces 665E&282E&514C

eps trie sub amp ret sea 動態 應該 signed

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