(字典树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 }
时间: 2024-10-14 07:30:36

(字典树3道水题)codeforces 665E&282E&514C的相关文章

POJ百道水题列表

以下是poj百道水题,新手可以考虑从这里刷起 搜索1002 Fire Net1004 Anagrams by Stack1005 Jugs1008 Gnome Tetravex1091 Knight Moves1101 Gamblers1204 Additive equations 1221 Risk1230 Legendary Pokemon1249 Pushing Boxes 1364 Machine Schedule1368 BOAT1406 Jungle Roads1411 Annive

刷了500道水题是什么体验?

并没有什么卵用. 我马上大二了,大一两学期目测切了1000道水题了,毫无意义. 至今不理解kmp和后缀数组,只会模板.数论和博弈论是什么?能吃吗?只会打表.图论至今不会tarjan,话说dlx是什么?插头dp,这是什么?数据结构还好,经常做高中生的题,可持久化可持久化线段树也能花一下午时间写出来,然而并不会考. 平时做题只刷水题,遇到难题的时候,随手搜题解,看了看,哇,这居然能这么搞!然后抄一遍别人代码,交上去ac. cf一年几乎没缺过,花了大一上半年时间才滚上div1.然而至今紫号一堆,黄名一

大数--几道水题,用来学学JAVA

几道水题,练习一下JAVA写大数 poj2305  Basic remains 大数可以直接用非十进制读入,读入的数在变量中是十进制的 输出的时候要先用BigInteger的toString方法转换为相应的进制 1 import java.math.*; 2 import java.util.*; 3 class Main 4 { 5 public static void main(String[] args) 6 { 7 Scanner cin = new Scanner(System.in)

水题 Codeforces Round #286 (Div. 2) A Mr. Kitayuta&#39;s Gift

题目传送门 1 /* 2 水题:vector容器实现插入操作,暴力进行判断是否为回文串 3 */ 4 #include <cstdio> 5 #include <iostream> 6 #include <algorithm> 7 #include <cstring> 8 #include <string> 9 #include <vector> 10 using namespace std; 11 12 const int MAXN

HDU1166 敌兵布阵 树状数组水题

中文题目,很简单的题目,区间求和,当然对于线段树来说也很水,为了练习一下树状数组,多做做水题吧,加深理解,并且打好基础,我算是被没打好基础给吓坏了,宁可多花几个小时 刷刷水题扎实点, 很裸的题目 操作也很裸,了解树状数组的肯定能做 #include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #include<string&g

水题 codeforces 158B Taxi

贪心题,虽然是道水题,但是因为当时花了点时间,而且用了两种方法,并且尚存一些问题没有解决,所以写下来:先讲贪心的做法:先将数据从大到小排序:将大的一边和小的一边相加,与4进行比较:如果小于等于4,队伍-2,车数+1,再与小的一边相加,如果仍满足条件,队伍-1,车数不变,重复过程,直到不满足条件:如果大于4,队伍-1,车数+1先贴超时错误的代码: #include<iostream>#include<stdio.h>#include<queue>#include<f

水题 Codeforces Round #303 (Div. 2) A. Toy Cars

题目传送门 1 /* 2 题意:5种情况对应对应第i或j辆车翻了没 3 水题:其实就看对角线的上半边就可以了,vis判断,可惜WA了一次 4 3: if both cars turned over during the collision. 5 是指i,j两辆车,而不是全部 6 */ 7 #include <cstdio> 8 #include <algorithm> 9 #include <cstring> 10 #include <cmath> 11 #

水题 Codeforces Round #299 (Div. 2) A. Tavas and Nafas

题目传送门 1 /* 2 很简单的水题,晚上累了,刷刷水题开心一下:) 3 */ 4 #include <bits/stdc++.h> 5 using namespace std; 6 7 char s1[11][10] = {"zero", "one", "two", "three", "four", "five", "six", "seven

水题 Codeforces Round #302 (Div. 2) A Set of Strings

题目传送门 1 /* 2 题意:一个字符串分割成k段,每段开头字母不相同 3 水题:记录每个字母出现的次数,每一次分割把首字母的次数降为0,最后一段直接全部输出 4 */ 5 #include <cstdio> 6 #include <iostream> 7 #include <cstring> 8 #include <string> 9 #include <algorithm> 10 using namespace std; 11 12 con