Vasiliy's Multiset

链接:http://acm.hust.edu.cn/vjudge/problem/460314/origin

题目:

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:

  1. "+ x" — add integer x to multiset A.
  2. "- 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.
  3. "? 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.



题意:有一个空的列表,里面可以存数字。共有3种操作:+:存一个(相同数字视为不同个体),-:删除一个(相同的数字只删掉一个),?:询问:给一个数,求列表里和这个数进行异或的最大值,输出这个结果

分析:,,,看了题解才知道看有一种方法可以算是二叉字典树(又或者叫二进制数字数????)来解决这个问题。就是把数字的二进制当作字符,利用字典树的查找特性来解决这个问题。然而知道了数据结构还是错的一塌糊涂。首先比对最大值,所以存的时候要从最高位开始,再之后。。。。。。。居然有什么都没存就开始查的情况。。。所以一定要预先存一个零进去。(记得维护一个n来记录这个数字存了几个)

题解:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <functional>
#include <cmath>
#include <cctype>
#include <cfloat>
#include <climits>
#include <complex>
#include <deque>
#include <list>
#include <set>
#include <utility>
#define rt return
#define fr freopen("in.txt","r",stdin)
#define fw freopen("out.txt","w",stdout)
#define ll long long
#define ull unsigned long long
#define detie ios_base::sync_with_stdio(false);cin.tie(false);cout.tie(false)
#define pii pair<int,int>
#define lowbit(x) x&(-x)
using namespace std;
#define maxi 0x3f3f3f3f
#define MAX 100020

struct Node
{
	int count;
	Node* next[2];
	Node() :count(0) { memset(next, 0, sizeof next); }
}*root;

void insert(int num)
{
	Node* p = root;
	for (int i = 30; i >= 0; i--)
	{
		int k = (num&(1 << i)) ? 1 : 0;
		if (!p->next[k])
			p->next[k] = new Node;
		p = p->next[k];
		p->count++;
	}
}

void del(int num)
{
	Node* p = root;
	for (int i = 30; i >= 0; i--)
	{
		int k = (num&(1 << i)) ? 1 : 0;
		p = p->next[k];
		if (p->count > 0)
			p->count--;
	}
}

int find(int num)
{
	Node* p = root;
	int sum = 0;
	for (int i = 30; i >= 0; i--)
	{
		int k = 1 - ((num&(1 << i)) ? 1 : 0);
		if (p->next[k] && p->next[k]->count > 0)
		{
			p = p->next[k];
			sum += 1 << i;
		}
		else if (p->next[1 - k])
			p = p->next[1 - k];
	}
	rt sum;
}

int main()
{
	//fr;
	detie;
	root = new Node;
	int t;
	cin >> t;
	insert(0);//吗各级啊。。。。。可能在什么都没有的时候查。。
	while (t--)
	{
		char c;
		int num;
		cin >> c >> num;
		switch (c)
		{
		case '+':insert(num); break;
		case '-':del(num); break;
		case '?':cout << find(num) << endl; break;
		default:break;
		}
	}
	rt 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值