4604. 集合询问(unordered_map)

AcWing 4604. 集合询问 - AcWing

有一个整数集合,初始时集合为空。

现在,要对该集合进行 tt 次操作,操作分为以下三种:

  • + x,将一个非负整数 xx 添加至集合中。注意,集合中可以存在多个相同的整数。
  • - x,从集合中删除一个非负整数 xx。可以保证执行此操作时,集合中至少存在一个 xx。
  • ? s,询问操作,给定一个由 00 和 11 组成的模板 ss,请你计算并输出此时集合中有多少个元素可以与 ss 相匹配。

关于判断整数 xx 与模板 ss 是否匹配的具体方法如下:

  • 首先,在进行匹配判断前,应保证 xx 与 ss 位数相同,如果两者位数不同,则位数更少的一方需补充前导 00 至与位数更多的一方位数相同为止。
  • 从最高位开始,对每一位进行逐个判断,如果 ss 的第 ii 位为 00,则 xx 的第 ii 位必须为偶数,如果 ss 的第 ii 位为 11,则 xx 的第 ii 位必须为奇数。
  • 如果有任意一位不满足上述条件,则视为 xx 与 ss 不匹配。如果所有位均满足上述条件,则视为 xx 与 ss 匹配。

例如,如果 s=010s=010,则 92、2212、50、41492、2212、50、414 与 ss 匹配,而 3、110、25、10303、110、25、1030 与 ss 不匹配。

输入格式

第一行包含整数 tt,表示操作次数。

接下来 tt 行,每行包含一个操作,格式如题面描述。

保证至少存在一个查询操作。

输出格式

每个查询操作输出一行结果,一个整数,表示集合中与 ss 匹配的元素个数。

数据范围

前 44 个测试点满足 1≤t≤201≤t≤20。
所有测试点满足 1≤t≤1051≤t≤105,0≤x<10180≤x<1018,ss 的长度范围 [1,18][1,18]。

输入样例1:

12
+ 1
+ 241
? 1
+ 361
- 241
? 0101
+ 101
? 101
- 101
? 101
+ 4000
? 0

输出样例1:

2
1
2
1
1

输入样例2:

5
+ 200
+ 200
? 0
- 200
? 0

输出样例2:

2
1

思路:

这道题刚看上去非常的懵b,注意到我们输入的数长度最大是18,我们不妨设一种极端情况,每次输入的数的长度都是18,然后我们把他的每一位都根据题意构造出一个新的数(只包含0和1,代表他这一位是偶数还是奇数,方便后续对照01串),注意到t 最大为1e5,1e5*18,这时候留给我们查询的时间就不多了,所以想到了unordered_map

#include<iostream>
#include<unordered_map>
#define int long long
using namespace std;
int n;
unordered_map<int,int>mp,get_x;
int get(int x) {
	int ans=0,res=0;
	int stk[20],top=0;
	while(x) {
		stk[++top]=(x%10)%2;
		x/=10;
	}
	while(top) {
		ans=ans*10+stk[top--];
	}
	return ans;
}
signed main() {
	cin>>n;
	while(n--) {
		char ch;
		int x;
		cin>>ch>>x;
		if(ch=='+') {
			if(!get_x.count(x)) {
				//这个数没有计算过
				//count()返回指定元素出现的次数
				get_x[x]=get(x);//里面记录x每位的偶数与奇数情况
			}
			mp[get_x[x]]++;
		} else if(ch=='-') {
			mp[get_x[x]]--;
		} else {
			cout<<mp[x]<<endl;
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值