社区讨论
启发式合并如何卡常?
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 条回复,欢迎继续交流。
正在加载回复...