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
",st.query(s));
112     }
113 
114     return 0;
115 }
View Code

用数组标记:

 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
",num[ans]);
41     }
42 
43     return 0;
44 }
View Code
原文地址:https://www.cnblogs.com/2cm-miao/p/5874796.html