zoukankan      html  css  js  c++  java
  • (字典树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
    ", 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 }
  • 相关阅读:
    4:4 自定义拦截器
    DDD学习笔记一
    Winform/WPF国际化处理
    NPOI 操作Excel
    将输入的字符串进行大写格式化
    将输入的字符串分2个字符添加空格并大写格式化
    VS使用技巧
    NotifyIcon用法
    C#Winfrom系统打印机调用/设置默认打印机
    TextBox(只允许输入字母或者数字)——重写控件
  • 原文地址:https://www.cnblogs.com/tak-fate/p/6882812.html
Copyright © 2011-2022 走看看