【CF706D】Vasiliy‘s Multiset (Trie字典树求异或+添加 删除 查询操作)

Vasiliy’s Multiset

题目大意:

有三种类型的查询:
“+ x” - 添加一个整数 X。
“ - x” - 删除一次整数 X。它保证至少有一个 X 存在于查询前的集合中。
“?x” - 给定整数 X 并且需要计算该值和一个整数Y的按位异或(也称为XOR)的最大值
这是一个允许相等元素的集合。

解题思路:

如果没有删除的话就是字典树求异或和模板题了,而现在需要有删除操作,我们新开一个index数组记录一下已有的节点即可(不能开bool数组,因为集合中可能有重复元素),添加就+1,删除-1,查询的时候>=1才可以到达此节点。

一定要记得提前把 0插入倒树里并标记为1,insert(0,1),一开始忘了这个操作,然后wa了5次

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int MAXN = 200007;
int t[MAXN<<5][3],tot=1,index[MAXN<<5];

void insert(int x,int w){                         //插入到字典树
    int p=1;
    for(int k=31;k>=0;k--){               //转换成01串
        int ch=x>>k&1;                      // if(x&(1<<i)) ch=1; else ch=0;
        if(!t[p][ch]){
        	t[p][ch]=++tot;
		} 
        p=t[p][ch];
        index[p]+=w;
    }
}

int search(int x){
    int p=1,ans=0;
    for(int k=31;k>=0;k--){
        int ch=x>>k&1;
        if(index[t[p][ch^1]]){                     //尽可能找不一样的,贪心思想
            p=t[p][ch^1];
            ans|=1<<k;
        }else p=t[p][ch];
    }
    return ans;
}


int main(){
    int n,m,T,w;
    char op[2];
    memset(t,0,sizeof t);
    memset(index,0,sizeof index);
    scanf("%d",&T);
    insert(0,1);       //////////////////////////////////////提前把0标记为1
    for(int k=1;k<=T;k++){
    	scanf("%s%d",op,&n);
    	if(op[0]=='+') insert(n,1);
        else if(op[0]=='-') insert(n,-1);
        else printf("%d\n", search(n));
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43872264/article/details/107660938
今日推荐