• (字典树)codeforces


    原题链接:http://codeforces.com/problemset/problem/706/D


    题意:需要你模拟一个多重集合(初始拥有0),该集合拥有三个功能

    1、+ x  增加一个x(可以同时存在多个x,因为是多重集合)

    2、-  x 去掉一个x

    3、? x  输出在这个集合中和x异或最大的值。


    分析:有20万个操作,很容易想到树形数据结构,我们可以看到每个x最多只有10^9,而1<<30比10^9大一点,所以10^9次方最多就是29位的01串,可以维护一个字典树。

    每个节点有两个分支,0和1,深度最深也就是29。

    我一开始想到把01串倒着往里插,因为在x进行&和>>1操作可以很方便达到这一点,但是+和-操作如果这样实现,就很难实现?操作了。

    因为根据异或运算就是对应位相同为0,不同为1,而在01串中,越往左的1在10进制中的值就越大。

    要取得异或的最大值,很容易想到就是贪心,从最左边开始比较,每次取和自己不同的那个分支,往下走,如果与自己不同的那个分支未曾建立过,或者统计的cnt已经==0(-操作删除了)就走相同的那一分支。

    同时我们能够发现可以直接正着插,也就是说不管你的有效01串有几位,都把29位包含前导0的01串全都存进去。这就方便了?操作。


    代码:

      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 
     28 struct  Trie_node {
     29     int cnt;
     30     int next[2];
     31 }tree[10000010];
     32 int nxt;
     33 
     34 int  createTrieNode() {
     35     memset(&tree[nxt], 0, sizeof(Trie_node));
     36     return nxt++;
     37 }
     38 
     39 void Trie_insert(int val) {
     40     int rt=0;
     41     char bir[30];
     42     for(int i=29;i>=0;i--){
     43         bir[i]=(val&1)+'0';
     44         val>>=1;
     45     }
     46     for(int i=0;i<30;i++){
     47         int id=bir[i]-'0';
     48         if(!tree[rt].next[id]){
     49             tree[rt].next[id]=createTrieNode();
     50         }
     51         rt=tree[rt].next[id];
     52         tree[rt].cnt++;
     53     }
     54 }
     55 
     56 void Trie_remove(int val){
     57     int rt=0;
     58     char bir[30];
     59     for(int i=29;i>=0;i--){
     60         bir[i]=(val&1)+'0';
     61         val>>=1;
     62     }
     63     for(int i=0;i<30;i++){
     64         int id=bir[i]-'0';
     65         rt=tree[rt].next[id];
     66         tree[rt].cnt--;
     67     }
     68 
     69 }
     70 
     71 int Trie_search(int val) {
     72     int rt=0;
     73     char res[30]={0};
     74     int ans=0;
     75     char bir[30];
     76     for(int i=29;i>=0;i--){
     77         bir[i]=(val&1)+'0';
     78         val>>=1;
     79     }
     80     for(int i=0;i<30;i++){
     81         int id=bir[i]-'0';
     82         if(tree[rt].next[id^1]&&tree[tree[rt].next[id^1]].cnt>0){
     83             rt=tree[rt].next[id^1];
     84             res[i]='1';
     85         }
     86         else{
     87             rt=tree[rt].next[id];
     88             res[i]='0';
     89         }
     90     }
     91     int k=0;
     92     for(;k<30&&res[k]=='0';){
     93         k++;
     94     }
     95     for(int i=29;i>=k;i--){
     96         ans+=(1<<(29-i))*(res[i]-'0');
     97     }
     98     return ans;
     99 }
    100 
    101 
    102 void init(){
    103     nxt=1;
    104     memset(&tree[0],0,sizeof(Trie_node));
    105 }
    106 
    107 char op[2];
    108 int v;
    109 
    110 void solve() {
    111     init();
    112     Trie_insert(0);
    113     int t;
    114     scanf("%d",&t);
    115     while(t--){
    116         scanf("%s%d",op,&v);
    117         if(op[0]=='+')Trie_insert(v);
    118         else if(op[0]=='-')Trie_remove(v);
    119         else if((op[0]=='?'))printf("%d
    ",Trie_search(v));
    120     }
    121 }
    122 
    123 
    124 
    125 
    126 int main() {
    127 
    128 #ifndef ONLINE_JUDGE
    129     freopen("in.txt", "r", stdin);
    130     //freopen("out.txt", "w", stdout);
    131 #endif
    132     //iostream::sync_with_stdio(false);
    133     solve();
    134     return 0;
    135 }
  • 相关阅读:
    bfs两种记录路径方法
    次小生成树
    2018 ICPC 区域赛 焦作场 D. Keiichi Tsuchiya the Drift King(计算几何)
    数组分组
    POJ
    数位DP详解
    2018ICPC青岛 E
    HDU
    Google工程师打造Remix OS系统 桌面版安卓下载
    使用angular封装echarts
  • 原文地址:https://www.cnblogs.com/tak-fate/p/5874586.html
Copyright © 2020-2023  润新知