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

题目戳这

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

思路:用字典树来进行增删查的操作,并且每次把数字插入进字典树的时候,都要把数字补齐成18位,然后从左边开始插入进字典树,并且插入的时候按照奇偶数的位置把偶数换成零,把奇数换成一插入进字典树,查询的时候也是要把二进制补齐成18位,然后进行查询,删除的时候也是要把数字处理成01串。

p.s.这道题有两种做法,一种就是用字典树来进行增删查,还有一种就是把每个数都换成01串之后再处理成十进制,然后用数组标记的做法来进行增删查

用字典树:

  1 #include<stdio.h>
  2 #include<iostream>
  3 #include<string.h>
  4 #include<math.h>
  5 #include<algorithm>
  6 #include<vector>
  7 #include<string>
  8 #include<queue>
  9 #include<map>
 10 #include<stack>
 11 #include<set>
 12 #define ll long long
 13 #define maxn 100010
 14 #define PI acos(-1.0)    //圆周率
 15 const ll INF = 1e18;
 16 using namespace std;
 17 struct node
 18 {
 19     int sz;
 20     int ch[45*maxn][3];
 21     int sum[45*maxn];
 22
 23     void trie()
 24     {
 25         sz=1;
 26         memset(ch,0,sizeof(ch));
 27         memset(sum,0,sizeof(sum));
 28     }
 29
 30     void add(string x)
 31     {
 32         int len=x.length();
 33         int k=18-len;
 34         int u=0;
 35         for(int i=0;i<k;i++)
 36         {
 37             if(ch[u][0]==0)  ch[u][0]=sz++;
 38             u=ch[u][0];
 39         }
 40         for(int i=0;i<len;i++)
 41         {
 42             int f=x[i]-‘0‘;
 43             int t=0;
 44             if(f%2==0)  t=0;
 45             else  t=1;
 46
 47             if(ch[u][t]==0)  ch[u][t]=sz++;
 48             u=ch[u][t];
 49         }
 50
 51         sum[u]++;
 52     }
 53
 54     void del(string x)
 55     {
 56         int len=x.length();
 57         int u=0;
 58         int k=18-len;
 59
 60         for(int i=0;i<k;i++)
 61         {
 62             if(ch[u][0]==0)  ch[u][0]=sz++;
 63             u=ch[u][0];
 64         }
 65
 66         for(int i=0;i<len;i++)
 67         {
 68             int f=x[i]-‘0‘;
 69             int t=0;
 70             if(f%2==0)  t=0;
 71             else  t=1;
 72
 73             if(ch[u][t]==0)  ch[u][t]=sz++;
 74             u=ch[u][t];
 75         }
 76
 77         sum[u]--;
 78     }
 79
 80     int query(string x)
 81     {
 82         int len=x.length();
 83         int u=0;
 84         int k=18-len;
 85
 86         for(int i=0;i<k;i++)  u=ch[u][0];
 87
 88         for(int i=0;i<len;i++)
 89         {
 90             int t=x[i]-‘0‘;
 91             u=ch[u][t];
 92         }
 93
 94         return sum[u];
 95     }
 96 }st;
 97 int n;
 98 string s;
 99 char fu[3];
100 int main()
101 {
102     scanf("%d",&n);
103     st.trie();
104     for(int i=0;i<n;i++)
105     {
106         scanf("%s",fu);
107         cin>>s;
108
109         if(fu[0]==‘+‘)  st.add(s);
110         else if(fu[0]==‘-‘)  st.del(s);
111         else  printf("%d\n",st.query(s));
112     }
113
114     return 0;
115 }

用数组标记:

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<string.h>
 4 #include<math.h>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<string>
 8 #include<queue>
 9 #include<map>
10 #include<stack>
11 #include<set>
12 #define ll long long
13 #define maxn 100010
14 #define PI acos(-1.0)    //圆周率
15 const ll INF = 1e18;
16 using namespace std;
17 ll num[45*maxn];
18 int n;
19 int main()
20 {
21     scanf("%d",&n);
22     ll k;
23     char s[3];
24     for(int i=0;i<n;i++)
25     {
26         scanf("%s %I64d",s,&k);
27         int cnt=0;
28         int f=0;
29         ll ans=0;
30         while(k)
31         {
32             cnt=k%10;
33             k/=10;
34             if(cnt%2!=0)  ans+=(ll)pow(2,f);
35             f++;
36         }
37
38         if(s[0]==‘+‘)  num[ans]++;
39         else if(s[0]==‘-‘)  num[ans]--;
40         else  printf("%d\n",num[ans]);
41     }
42
43     return 0;
44 }

时间: 2024-09-30 18:33:02

Codeforces Round #371 (Div. 2) C. Sonya and Queries(字典树)的相关文章

Codeforces Round #590 (Div. 3) D. Distinct Characters Queries(线段树, 位运算)

链接: https://codeforces.com/contest/1234/problem/D 题意: You are given a string s consisting of lowercase Latin letters and q queries for this string. Recall that the substring s[l;r] of the string s is the string slsl+1-sr. For example, the substrings

Codeforces Round #371 (Div. 1)

A: 题目大意: 在一个multiset中要求支持3种操作: 1.增加一个数 2.删去一个数 3.给出一个01序列,问multiset中有多少这样的数,把它的十进制表示中的奇数改成1,偶数改成0后和给出的01序列相等(比较时如果长度不等各自用0补齐) 题解: 1.我的做法是用Trie数来存储,先将所有数用0补齐成长度为18位,然后就是Trie的操作了. 2.官方题解中更好的做法是,直接将每个数的十进制表示中的奇数改成1,偶数改成0,比如12345,然后把它看成二进制数10101,还原成十进制是2

递推 Codeforces Round #186 (Div. 2) B. Ilya and Queries

题目传送门 1 /* 2 递推:用cnt记录前缀值,查询区间时,两个区间相减 3 */ 4 #include <cstdio> 5 #include <algorithm> 6 #include <cmath> 7 #include <cstring> 8 using namespace std; 9 10 const int MAXN = 1e5 + 10; 11 const int INF = 0x3f3f3f3f; 12 char s[MAXN]; 1

Codeforces Round #216 (Div. 2) E. Valera and Queries (BIT)

题目大意: 给出很多条分布在 x 轴上的线段. 然后给出很多点集,问这些点集分布在多少条不同的线段上. 思路分析: 把点集分散成若干条线段. 如果点集做出的线段包含了某一条给出的线段的话,也就是说这个点集上不会有点在这条线段上. 所以我们就是求出 点集做出的线段包含了多少个给出的线段就可以了. 那么也就是比较l r的大小,排序之后用BIT #include <cstdio> #include <iostream> #include <algorithm> #includ

Codeforces Round #406 (Div. 2) E. Till I Collapse(主席树)

题目链接:Codeforces Round #406 (Div. 2) E. Till I Collapse 题意: 给你n个数,对于每一个k(1<=k<=n),划分区间,每个区间只能有k个不同的数字, 问最小的划分区间的个数. 题解: 用主席树倒着将数插入,对于每个区间询问第k个不同数的位置就行了. #include<bits/stdc++.h> #define F(i,a,b) for(int i=a;i<=b;i++) #define ___ freopen("

Codeforces Round #371 (Div. 1) D. Animals and Puzzle 二维倍增

D. Animals and Puzzle 题目连接: http://codeforces.com/contest/713/problem/D Description Owl Sonya gave a huge lake puzzle of size n × m to hedgehog Filya as a birthday present. Friends immediately started to assemble the puzzle, but some parts of it turn

Codeforces Round #371 (Div. 2)B. Filya and Homework

题目链接:http://codeforces.com/problemset/problem/714/B 题目大意: 第一行输入一个n,第二行输入n个数,求是否能找出一个数x,使得n个数中的部分数加上x或部分数减去x ,n个数相等. 例如:5 1 3 3 2 1 输出: YES Init: x=1 情况,第一个数和最后一个数+x,第二三个数减去x ,则这n个数都为2(相等),故输出“YES” 解题思路: 对于刚才举的例子 可知 n个数只有三个元素 1 2 3 只要使得 2-1==3-2 即可满足条

Codeforces Round #495 (Div. 2) D. Sonya and Matrix

链接:http://codeforces.com/contest/1004/problem/D 题意:给你t个数字(a1,a2......at),要你组成一个n x m的矩阵,这个矩阵满足这样的条件 ①矩阵里面的元素到"0"这个元素的曼哈顿距离为元素值大小.曼哈顿距离:两个点坐标差的绝对值之和. 现在问你的是输出n,m以及元素"0"的坐标(x,y);如果不存在这样的矩阵,输出"-1". 注意:起点坐标为(1,1). 分析:首先我们假设"

Codeforces Round #371 (Div. 2) C

传送门  map或者字典数的应用 简单题 题意: 思路: AC代码: 1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 #include<map> 5 #include<algorithm> 6 #include<cstdio> 7 #define max(a,b) a>b?a:b 8 #define F(i,a,b) for(int i=a;i<=b