• 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
  • 相关阅读:
    POJ1470 Closest Common Ancestors(LCA入门)
    POJ1330 Nearest Common Ancestors(倍增LCA算法求无边权树的模板)
    HDU3078 Network (倍增LCA算法求树链)
    HDU2874 Connections between cities(并查集+倍增LCA算法求森林最短路)
    HDU2586 How far away?(倍增LCA算法求带边权树上最短路)
    POJ1062 昂贵的聘礼
    HDU4725 The Shortest Path in Nya Graph(堆优化的dijkstra算法)
    数据仓库详解:包括概念、架构及设计
    利用行为标签构建用户画像
    Spark SQL深度理解篇:模块实现、代码结构及执行流程总览(2)
  • 原文地址:https://www.cnblogs.com/2cm-miao/p/5874796.html
Copyright © 2020-2023  润新知