(字典树)codeforces - 713A Sonya and Queries

原题链接:http://codeforces.com/problemset/problem/713/Attr



题意:一个集合,有三个操作,+-?,其中+和-和上一次cf的字典树那题是一个意思,?操作是统计满足01模式串的字典树中数的个数。如果模式串比字典中的数长就补全数,如果数长就补全模式串。



分析:

这题居然写了一个小时,一开始20分钟差不多写完了,但是一直坑在两种长度不同的情况上,后来仔细一想,卧槽,so easy啊,直接默认全部补全到18位不就行了。。那样这题就是一个简单的求前缀的个数。

其实思路和上次的差不多,都是补全后插入。我好年轻。



代码:

  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
 16 using namespace std;
 17
 18 typedef long long ll;
 19 typedef unsigned long long ull;
 20 #define inf (0x3f3f3f3f)
 21 #define lnf (0x3f3f3f3f3f3f3f3f)
 22 #define eps (1e-8)
 23 int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
 24
 25 //--------------------------
 26
 27 typedef struct  Trie_node {
 28     int cnt;
 29     struct  Trie_node* next[2];
 30     int exist;
 31 } TrieNode,*Trie;
 32
 33 TrieNode* createTrieNode() {
 34     TrieNode* node = (TrieNode *)malloc(sizeof(TrieNode));
 35     node->cnt = 0;
 36     node->exist =0;
 37     memset(node->next, 0, sizeof(node->next));
 38     return node;
 39 }
 40
 41 void Trie_insert(Trie root, ll &nn) {
 42     Trie node = root;
 43     for(int i=0;i<18;i++){
 44         int id=nn&1;
 45         if(node->next[id]==NULL)node->next[id]=createTrieNode();
 46         node=node->next[id];
 47         node->cnt++;
 48         nn/=10;
 49     }
 50 }
 51
 52 void Trie_remove(Trie root,ll &nn){
 53     Trie node = root;
 54     for(int i=0;i<18;i++){
 55         int id=nn&1;
 56         node=node->next[id];
 57         node->cnt--;
 58         nn/=10;
 59     }
 60 }
 61
 62 int Trie_search(Trie root, string word) {
 63     Trie node = root;
 64     reverse(word.begin(),word.end());
 65     int len=word.length();
 66     for(int i=0;i<18-len;i++){
 67         word.push_back(‘0‘);
 68     }
 69     for(int i=0;i<word.length();i++) {
 70         int id = word[i]-‘0‘;
 71         node = node->next[id];
 72         if(node==NULL||node->cnt<=0)return 0;
 73     }
 74     return node->cnt;
 75 }
 76 char op[2];
 77 char num[20];
 78 ll nn;
 79 void solve() {
 80     TrieNode *root=createTrieNode();
 81     int n;
 82     scanf("%d",&n);
 83     for(int i=0;i<n;i++){
 84         scanf("%s",op);
 85         if(op[0]==‘+‘){
 86             scanf("%I64d",&nn);
 87             Trie_insert(root,nn);
 88         }
 89         if(op[0]==‘-‘){
 90             scanf("%I64d",&nn);
 91             Trie_remove(root,nn);
 92         }
 93         if(op[0]==‘?‘){
 94             scanf("%s",num);
 95             printf("%d\n",Trie_search(root,num));
 96         }
 97     }
 98 }
 99
100
101
102
103 int main() {
104
105
106 #ifndef ONLINE_JUDGE
107     freopen("in.txt", "r", stdin);
108     //freopen("out.txt", "w", stdout);
109
110 #endif
111     //iostream::sync_with_stdio(false);
112     solve();
113     return 0;
114 }
时间: 2024-08-08 13:03:23

(字典树)codeforces - 713A Sonya and Queries的相关文章

Codeforces 713A. Sonya and Queries

题目链接:http://codeforces.com/problemset/problem/713/A 题意: Sonya 有一个可放置重复元素的集合 multiset, 初始状态为空, 现给予三种类型的操作: + ai : 把 ai 加入到集合 multiset 中, 可能出现重复元素. -  aj : 把 aj 从集合 multiset 中删除, 保证集合中一定存在这个元素. ? s  : 统计集合中现有的元素和模式串 s 匹配的个数.s 是一个 “01” 串, 其中 "0" 代表

C. Watto and Mechanism 字典树 Codeforces Round #291 (Div. 2)

C. Watto and Mechanism time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output Watto, the owner of a spare parts store, has recently got an order for the mechanism that can process strings in a ce

[字典树] Codeforces 557E Ann and Half-Palindrome

题意: 给一个长度为5000的ab串,问你第k大的半回文子串是什么 所谓的半回文串就是下标是奇数的位置前后相等就好了. 思路: 首先发现串的长度只有5000,可以做一个类似区间dp的预处理 处理出dp[i][j]代表第i到j子串是不是半回文子串 然后依次把原串的所有子串插入字典树,并在节点标记个数 然后最后dfs一下k个就好了 代码: #include"cstdlib" #include"cstdio" #include"cstring" #in

Codeforces cf 713A Sonya and Queries

[题意:] t次操作,每次操作有下述三种类型: + a 往multiset中增加一个非负整数a,允许相同的数出现 - a 从multiset中减去一个非负整数a,执行此操作时保证multiset存在该非负整数a ? s 询问multiset中有多少个数与模式串s匹配(匹配的定义:模式串中,'0'表示该位为偶数,'1'表示该位为奇数) 即s与a从右往左,相对应的奇偶性一致时(长度不一致时,在较短的前面补0),称为二者匹配 输出与模式串s匹配的数的个数 [分析:] 题目说a,s最多都是18位,而且要

Codeforces Round #371 (Div. 2) C. Sonya and Queries(字典树)

题目戳这 题意:给你一个数字 n ,然后 n 组输入,如果第一个字符是+,就把后面的那个数字加入到集合里面去,如果第一个字符是减号,就把后面的那个数字从集合里面去掉一个,如果是问好,就开始配对,看看有多少个数字是和问号后面的数字是匹配的,是否配对的规则是,问好后面的数字都是二进制,一表示奇数,零表示偶数,如果集合中的数字长度和二进制的输入长度不一样,就把短的那个在前面加零,比如,二进制是101,集合中的数字是12,那就是101和012匹配,如果二进制是11,集合中的数字是12345,那么就是00

CodeForces 706D Vasiliy&#39;s Multiset (字典树查询+贪心)

题意:最开始的时候有一个集合,集合里面只有一个元素0,现在有q次操作,操作分为3种: + x: 表示向集合中添加一个元素x - x:表示删除集合中值为x的一个元素 ? x:表示查询集合中与x异或的最大值为多少 析:这是一个字典树的应用,不过确实没看出来....主要思想是这样,先用10进制数,转成二进制数,记下每个结点的0,1的个数,这样增加和删除,就是对01的删除, 剩下的就是查询,那么尽量让0和1XOR是最大的,所以,对于给定数,我们要去尽量他的XOR数,如果找到就加上,找不到,就找下一个.这

codeforces 455B A Lot of Games(博弈,字典树)

题目大意:给定n,表示字符串集合.给定k,表示进行了k次游戏,然后是n个字符串.每局开始,字符串为空串,然后两人轮流在末尾追加字符,保证新的字符串为集合中某字符串的前缀,不能操作者输,新一轮由上一句输的人先手. 解题思路:首先对字符集合建立字典树,然后根据博弈的必胜必败性质搜索出先手的决策状态,可决定胜败3,只能胜利2,只能失败1,不可掌控(即对手可决定胜败)0. 对于状态3,为必胜,可以采用前K-1场败,然后保证第K场自己先手,取必胜方案. 对于状态2,无论则们走都是赢的话,肯定是两个人轮流胜

codechef Xor Queries (可持久化字典树)

题目链接:codechef Xor Queries 题意: 题解: 一棵可持久化字典树就行了. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 5 const int N=5e5+7; 6 struct Node{int son[2],cnt;}ch[N*40]; 7 int root[N],cnt,ed,n; 8 9 void ins(int

Codeforces 706D Vasiliy&#39;s Multiset(可持久化字典树)

[题目链接] http://codeforces.com/problemset/problem/706/D [题目大意] 要求实现一个集合中的三个操作,1:在集合中加入一个元素x,2:从集合中删除一个元素x(保证x存在),3:要求从集合中选出一个数,使得其与给出的数x的异或值最大,输出这个异或值. [题解] 可以将所有的以二进制形式存在01字典树上,删除即插入权值为-1的二进制串,对于异或值最大的操作,我们只要在字典树上按位贪心,从最高位开始尽量保证该位存在最后就能得到答案.写代码的时候直接写了