• Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset(带删除的01字典树)


    D. Vasiliy’s Multiset
    time limit per test4 seconds
    memory limit per test256 megabytes
    inputstandard input
    outputstandard output
    Author has gone out of the stories about Vasiliy, so here is just a formal task description.

    You are given q queries and a multiset A, initially containing only integer 0. There are three types of queries:

    “+ x” — add integer x to multiset A.
    “- x” — erase one occurrence of integer x from multiset A. It’s guaranteed that at least one x is present in the multiset A before this query.
    “? x” — you are given integer x and need to compute the value , i.e. the maximum value of bitwise exclusive OR (also know as XOR) of integer x and some integer y from the multiset A.
    Multiset is a set, where equal elements are allowed.

    Input
    The first line of the input contains a single integer q (1 ≤ q ≤ 200 000) — the number of queries Vasiliy has to perform.

    Each of the following q lines of the input contains one of three characters ‘+’, ‘-’ or ‘?’ and an integer xi (1 ≤ xi ≤ 109). It’s guaranteed that there is at least one query of the third type.

    Note, that the integer 0 will always be present in the set A.

    Output
    For each query of the type ‘?’ print one integer — the maximum value of bitwise exclusive OR (XOR) of integer xi and some integer from the multiset A.

    Example
    inputCopy
    10
    + 8
    + 9
    + 11
    + 6
    + 1
    ? 3
    - 8
    ? 3
    ? 8
    ? 11
    outputCopy
    11
    10
    14
    13
    Note
    After first five operations multiset A contains integers 0, 8, 9, 11, 6 and 1.

    The answer for the sixth query is integer — maximum among integers , , , and .

    题意:给出q个操作,若操作带+号是向集合中插入这个数,带-号表示删除这个数,带问号表示,查询集合中的数与输入的数异或最大值,输出这个异或结果,注意题目要求0一直在树的根节点,也就是说,输入的数可以与集合中的任意一个值异或,也可以不异或(即与0异或)得到最大值。

    典型的01字典树,直接+号建树,根据-号删除相应节点,删除方法即对树上的节点走过的进行计数,那么就是cnt++和cnt–,删除时直接对路径上每个节点计数减一,注意不用动节点上创建的编号,因为这条编号可能是其他数的路径,删除了一个数不代表整个子树在此被截断。

    最后在查询时,既要存在这个被查询的节点,又要计数不为0,那么搜索到的就是经过删除的树,否则只像之前一样判断是否存在节点,会忽略删除的标记

    #include<bits/stdc++.h>///01字典树
    #define LL long long
    #define M(a,b) memset(a,b,sizeof a)
    using namespace std;
    const int maxn=1e5+7;
    int tre[maxn<<5][2];
    int cnt[maxn<<5];///标记节点走过次数,就不用关心原节点链接向哪个标号了
    int vis[maxn<<5];
    int q,tot=0;
    char flag[3];
    void insert(int a,int rt,int add)
    {
        for(int i=31; i>=0; i--)
        {
            int x=(a>>i)&1;
            if(!tre[rt][x])
            {
                tre[rt][x]=++tot;
                M(tre[tre[rt][x]],0);
            }
            rt=tre[rt][x];
            cnt[rt]+=add;///删除和插入就是对某个节点的经过次数计数
        }
        vis[rt]=a;
    }
    int finds(int a,int rt)
    {
        for(int i=31;i>=0;i--)
        {
            int x=(a>>i)&1;
            if(tre[rt][!x]&&cnt[tre[rt][!x]])rt=tre[rt][!x];///必须同时符合两个条件才能往这条子树上走
            else rt=tre[rt][x];
        }
        return vis[rt];
    }
    int main()
    {
        int tmp,rt=++tot;
        M(tre[rt],0);
        M(cnt,0);
        M(vis,0);
        scanf("%d",&q);
        while(q--)
        {
            scanf("%s",flag);
            scanf("%d",&tmp);
            if(flag[0]=='+') insert(tmp,rt,1);
            else if(flag[0]=='-') insert(tmp,rt,-1);
            else printf("%d
    ",max(tmp,tmp^finds(tmp,rt)));///因为0一直在根部,因此必须检查一下这个数异或0(输出自己)和异或集合中某个数来取最大值
        }
        return 0;
    }
    
  • 相关阅读:
    how to read openstack code: loading process
    how to read openstack code: request extension
    how to read openstack code: action extension
    b站刷赞 B站刷赞工具 bilibili评论刷赞 b站点赞
    利用邓西百度网盘消息群发工具对百度网盘的群组、好友进行管理,批量分享文件
    如何利用邓西百度网盘批量转存检测工具批量检测百度网盘失效分享链接
    如何使用邓西百度网盘批量重命名工具对百度网盘中的文件进行批量改名、删除等
    如何利用邓西百度网盘消息群发工具批量删除百度网盘单向好友
    如何利用工具自动通过百度网盘好友请求并发送消息或文件
    邓西百度网盘批量保存检测工具高级用法之分享链接以指定名称保存
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135726.html
Copyright © 2020-2023  润新知