社区讨论

启发式合并如何卡常?

P3273[SCOI2011] 棘手的操作参与者 22已保存回复 25

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
25 条
当前快照
1 份
快照标识符
@mlgxxu5w
此快照首次捕获于
2026/02/11 02:35
上周
此快照最后确认于
2026/02/11 02:40
上周
查看原帖
不是,我记得启发式合并常数挺小的啊,3e5,两 log 不是应该随便过吗,怎么还 T 了?
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int n,q;
int a[N],c[N],t[N],sum;
set<pair<int,int>> s[N];
multiset<int> f;
void init(){
	for(int i=1;i<=n;i++){
		c[i]=i;
		s[i].insert({a[i],i});
		f.insert(a[i]);
	}
}
int que_pos(int x){
	int w=c[x];
	return a[x]+t[w];
} 
int que_block(int x){
	int w=c[x];
	return (*(--s[w].end())).first+t[w];
}
int que_all(){
	return (*(--f.end()));
}
void mer(int x,int y){
	if(c[x]==c[y]) return;
	f.erase(f.find(que_block(x)));
	f.erase(f.find(que_block(y)));
	int u=c[x],v=c[y];
	if(s[u].size()<s[v].size()) swap(u,v),swap(x,y);
	for(auto [val,id]:s[v]){
		c[id]=u;
		s[u].insert({val+t[v]-t[u],id});
		a[id]+=t[v]-t[u];
	}
	s[v].clear();
	f.insert(que_block(x));
}
void add_pos(int x,int k){
	f.erase(f.find(que_block(x)));
	int w=c[x];
	s[w].erase({a[x],x});
	a[x]+=k;
	s[w].insert({a[x],x});
	f.insert(que_block(x));
}
void add_block(int x,int k){
	f.erase(f.find(que_block(x)));
	int w=c[x];
	t[w]+=k;
	f.insert(que_block(x));
}
void add_all(int k){
	sum+=k;
}
signed main(){
//	freopen("std.in","r",stdin);
//	freopen("std.out","w",stdout);
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	init();
	cin>>q;
	while(q--){
		string op;
		int x,y,k;
		cin>>op;
		if(op=="U"){
			cin>>x>>y;
			mer(x,y);
		}
		if(op=="A1"){
			cin>>x>>k;
			add_pos(x,k);
		}
		if(op=="A2"){
			cin>>x>>k;
			add_block(x,k);
		}
		if(op=="A3"){
			cin>>k;
			add_all(k);
		}
		if(op=="F1"){
			cin>>x;
			cout<<que_pos(x)+sum<<"\n";
		}
		if(op=="F2"){
			cin>>x;
			cout<<que_block(x)+sum<<"\n";
		}
		if(op=="F3"){
			cout<<que_all()+sum<<"\n";
		}
	} 
}

回复

25 条回复,欢迎继续交流。

正在加载回复...