Post

CF1862G(multiset集合)

CF1862G(multiset集合)

题意:
一个数组n可以进行如下操作:
先对数组排序,对 $[a_1,a_2,a_3,…,a_n] +[n,n-1,n-2,…,1] $ ,然后去重;重复该操作直至元素变为1,对数组k次询问,每次询问x,k,将 $a_x=k$ ,计算进行若干次操作后数组最后一个数
思路:
考虑对一个确定的数组操作,每次操作会使 $ a_{i-1} 和 a_{i} $的差值减1,当两者相等时消除一个,每次操作 $a_n+1$ ,且最后一个树必定包含 $a_n$ ,所以最后的数为 $ a_{max} +b_{max} $,b为相邻的差值,所以考虑维护每次两个数的最大值,用multiset维护,每次删除差值用extract(如果有多个相同的值只会删一个),删除a元素要删除该节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void solve(){
	int n;
	cin>>n;
	vector<int> a(n);
	for(int i=0;i<n;i++)cin>>a[i];
	multiset<int> s,d{0};
	auto add=[&](int x){
		auto it=s.insert(x);
		auto r=next(it);
		if(it!=s.begin())d.insert(x-*prev(it));
		if(r!=s.end())d.insert(*r-x);
		if(it!=s.begin()&&r!=s.end()){
			d.extract(*r-*prev(it));
		}
	};
	auto del=[&](int x){
		auto it=s.find(x);
		auto r=next(it);
		if(it!=s.begin())d.extract(x-*prev(it));
		if(r!=s.end())d.extract(*r-x);
		if(it!=s.begin()&&r!=s.end()){
			d.insert(*r-*prev(it));
		}
		s.erase(it);
	};
	for(int i=0;i<n;i++)add(a[i]);
	int q;
	cin>>q;
	while(q--){
		int x,y;
		cin>>x>>y;
		x--;
		del(a[x]);
		a[x]=y;
		add(a[x]);
		cout<<*s.rbegin()+*d.rbegin()<<" ";
	}
	cout<<"\n";
}
This post is licensed under CC BY 4.0 by the author.