CF706DVasiliy's Multiset Trie+贪心

Posted wzj-xhjbk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF706DVasiliy's Multiset Trie+贪心相关的知识,希望对你有一定的参考价值。

题目大意:需要维护一种数据结构,支持以下三种操作:插入一个数,删除一个数,查询该数据结构中的数异或给定数的最大值。

题解:如果没有删除操作就是一个标准的 Trie 上贪心求最大异或和问题。现在需要支持删除操作,因此,在树上每个节点维护一个额外的标记,表示有多少个数的某一位经过当前节点。插入操作依然只需修改树上一条链,而删除一个数时,同样需要将这条链上的标记值减 1 即可。这时便可以根据经过的每个点标记值是否为 0 进行贪心操作。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+1;

int trie[maxn<<5][2],tot=1,tag[maxn<<5];
int q,x;

void modify(int now,int idx,int val){
    if(idx<0)return;
    int ch=x>>idx&1;
    if(!trie[now][ch])trie[now][ch]=++tot;
    now=trie[now][ch],tag[now]+=val;
    modify(now,idx-1,val);
}

int query(int now,int idx,int ans){
    if(idx<0)return ans;
    int ch=x>>idx&1;
    if(tag[trie[now][ch^1]])now=trie[now][ch^1],ans|=1<<idx;
    else now=trie[now][ch];
    return query(now,idx-1,ans);
}

void solve(){
    char op[2];
    modify(1,31,1);
    while(q--){
        scanf("%s%d",op,&x);
        if(op[0]==‘+‘)modify(1,31,1);
        else if(op[0]==‘-‘)modify(1,31,-1);
        else printf("%d
",query(1,31,0));
    }
}

int main(){
    scanf("%d",&q);
    solve();
    return 0;
}

以上是关于CF706DVasiliy's Multiset Trie+贪心的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces 706D Vasiliy's Multiset

cf706D

Codeforces 706D Vasiliy's Multiset(可持久化字典树)

Vasiliy's Multiset CodeForces -706D || 01字典树模板

CF706C Hard problem (状态机dp)

trie树 Codeforces Round #367 D Vasiliy's Multiset