首页 > 其他分享 >Codeforces Round #830 (Div. 2)D2. Balance (Hard version)(数据结构)

Codeforces Round #830 (Div. 2)D2. Balance (Hard version)(数据结构)

时间:2022-10-24 13:24:25浏览次数:70  
标签:map 830 Hard Codeforces 查询 del 答案 集合 change

题目链接


题目大意

维护一个集合的mex,每次有三种操作:

  1. '+' x:将数 x 插入集合中
  2. '-' x:将数 x 移除集合
  3. '?' k:询问满足mex的数是k的倍数 既集合中未出现的数中最小的数可以整除k

题目思路:

其实如果只维护操作1,3是比较容易的,只需要每次记录数是否在集合中,并且在每次查询的时候记录下本次数k的答案(每次倍增的查询即可),以便下次查询的时候不必重复查询。

而现在因为有了 操作,所以导致了原先的答案有可能会被他影响。所以我们可以将这种影响记录下来用于查询经过操作后的答案。

所以我们维护一个map<int,vector> change

change[x] 表示的是当x受到减操作后,会影响到的数
\(~~\)例如:当我们查询k = 2时,会经过2,4,6,8,10...,那就说明2的改变会影响这些数的值的改变:

ans[x] 2 4 6 8 10 ...
change[last[x]] 2 2 2 2,4 2 ...

当last[x]受到改变时,例如当我们删除了4时,我们便可以直接遍历change[4],说明2的答案在这个减操作后会被影响,此时查询2时的答案便是4(如果只删除了4)

此外我们还需要维护一个set,表示数的答案区间内的mex,通俗点讲就是k的倍数中哪些数当前不在集合内,哪些数在集合内
map<int,set> del
当我们删除这个数时便insert,否则erase,我们维护的是数x的mex

结合change以后,我们每次进行 '+' || '-' 操作时,维护一下del
每次查询时如果存在del.size()>0,说明答案就是*del[x].begin()
否则倍增查询答案


代码实现

# include<iostream>
# include<bits/stdc++.h>
using namespace std;
# define int long long
# define endl "\n"
const int N = 5e5 + 10;
void solve() {
	int n;
	cin >> n;
	map<int, int> ans;
	map<int, bool> vis;
	map<int,vector<int> > change;
	map<int,set<int>> del;
	
	while(n--){
		char op;
		int x;
		cin>>op>>x;
		if(op == '+'){
			vis[x] = 1;
			for(auto y:change[x]){
				del[y].erase(x);
			}
		}
		else if(op == '-'){
			vis[x] = 0;
			for(auto y:change[x]){
				del[y].insert(x);
			}
		}
		else{
			if(!ans[x]) ans[x] = x;
			if(del[x].size()){
				cout<<*del[x].begin()<<endl;
			}
			else{
				while(vis[ans[x]]){
					change[ans[x]].push_back(x);
					ans[x] += x;
				}
				cout<<ans[x]<<endl;
			}
		}
	}
}
int tt;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	tt = 1;


//	cin >> tt;
	while (tt--)solve();


	return 0;
}

标签:map,830,Hard,Codeforces,查询,del,答案,集合,change
From: https://www.cnblogs.com/empty-y/p/16821163.html

相关文章

  • Codeforces Round #829 (Div. 2) E // 概率dp
    题目来源:CodeforcesRound#829(Div.2)E-WishIKnewHowtoSort题目链接:Problem-E-Codeforces题意给定大小为\(n\)的仅包含\(0\)、\(1\)的数组\(a\),每......
  • Codeforces Round #830 (Div. 2)
    AB太简单了,不写解法了。CF1732CSheikh我们观察一下\(f(l,r)=\mathrm{sum}(l,r)-\mathrm{xor}(l,r)\)的性质。考虑假如一个数\(x\),对\(\mathrm{sum}\)的贡献为\(......
  • Codeforces Round #829 (Div. 2) E Wish I Knew How to Sort
    WishIKnewHowtoSort概率dp设计一个\(dp[i]\)表示还需要进行\(i\)次有效移动的概率何为有效移动?最后的数组是\(0\)在左边,\(1\)在右边因此只有把两个在错误......
  • Codeforces Round #829 (Div. 2) D Factorial Divisibility
    FactorialDivisibility模拟合....合成大西瓜?枚举每个阶乘因子,提取公因式之后有很多散着的\(1\),然后判断能不能合成当前倍数#include<iostream>#include<cstdio>#......
  • Codeforces Round #829 (Div. 1/Div. 2) 1753 A B C D 题解
    Div1A/2C.MakeNonzeroSum令最后每个\(a_i\)的系数为\(c_i\)(\(c_i=1/-1\)),发现只要满足\(c_1=1\)(下标从1开始),且c中没有两个-1相连,就一定能找出一种划分方式。那我......
  • Codeforces Round #830 C1. Sheikh(Easy version)
    题意给定一个长为\(n\)的非负整数序列\(\{a_n\}\),求\(l,r\)使\(f(l,r)=\text{sum}(l,r)-\text{xor}(l,r)\)最大,若答案不唯一,使\(r-l\)尽可能小,若仍不唯一,输出任意答案。......
  • Codeforces Round #747 (Div. 2) D Educational Codeforces Round 115 D
    D.TheNumberofImposters显然我们对于每一个关系就相当于连一个无向边我们显然对于每一个连通块来讲我们确定其中一个也就确定了这个连通块里的所有就相当于二分图......
  • Codeforces Round #829 (Div. 2)
    咕咕咕。C2.MakeNonzeroSum(hardversion)易得有奇数个非零值时无解。现在考虑将相邻的两个非零值配对,只要每一个非零值对都搞成和为零,总的和就为零。由于非零值只......
  • Educational Codeforces Round 137 (Rated for Div. 2) A-F
    比赛链接A题解知识点:数学。\(4\)位密码,由两个不同的数码组成,一共有\(C_4^2\)种方案。从\(10-n\)个数字选两个,有\(C_{10-n}^2\)种方案。结果为\(3(10-n)(9-n)\)......
  • Codeforces Round #829 (Div. 2) D. Factorial Divisibility(数学)
    题目链接题目大意:\(~~\)给定n个正整数和一个数k,问这n个数的阶乘之和能不能被k的阶乘整除既:(a\(_{1}\)!+a\(_{2}\)!+a\(_{3}\)!+....+a\(_{n}\)!)\(~\)%\(~\)k!\(~\)==......