Submission #884471

#TimeUsernameProblemLanguageResultExecution timeMemory
884471willychanSecurity Guard (JOI23_guard)C++17
100 / 100
809 ms59752 KiB
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//#include<bits/extc++.h>
//__gnu_pbds
struct node{
	ll prio;
	int u,v;
	node* cd=nullptr;
	node* sb=nullptr;
	int size = 1;
};


node* merge(node* a,node* b){
		if(a==nullptr) return b;
		if(b==nullptr) return a;
		if(a->prio>b->prio) {
			a->sb = b->cd;
			b->cd = a;
			b->size+=a->size;
			return b;
		}else{
			b->sb = a->cd;	
			a->cd = b;
			a->size+=b->size;
			return a;
		}
		assert(1==0);
		return a;
}

node* merge_sb(node *a){
	if(a==nullptr) return a;
	if(a->sb==nullptr) return a;
	return merge(merge(a,a->sb),merge_sb(a->sb->sb));
}
int get_size(node* a){
	if(a==nullptr) return 0;
	return a->size;
}

node* pop(node* a){
	assert(a!=nullptr);
	int z  = get_size(a);
	node* ans = merge_sb(a->cd);
	if(ans!=nullptr) ans->size = z-1;
	return ans;
}

const int N = 2e5+5;
int P[N];
int A[N];
int query(int x){
	if(x!=P[x])  P[x] = query(P[x]);
	return P[x];
}

void join(int a,int b){
	a = query(a);
	b = query(b);
	if(a==b) return;
	P[a]=b;
}


node* R[N];

ll cost[N];

priority_queue<pair<ll,int>,vector<pair<ll,int> > ,greater<pair<ll,int> > > pq;

bool taken[N];


int main(){
	ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int n,m,q;cin>>n>>m>>q;
	for(int i=1;i<=n;i++) P[i]=i;
	for(int i=1;i<=n;i++) cin>>A[i];
	ll additional = 0;
	vector<ll> ans(n);
	pair<ll,int> maxn = {-1,-1};
	pair<ll,int> minn = {1e18,-1};
	for(int i=1;i<=n;i++){
		ans[n-1]+=A[i];
		additional-=A[i];
		maxn = max(maxn,{A[i],i});
		minn = min(minn,{A[i],i});
	}
	additional+=maxn.first;
	int ONE = minn.second;
	ans[n-1]+=1LL*(n-2)*A[ONE];
	/*
	step?:
	find the smallest cost and the two component and merge them
	repeat
	find the smallest cost component
		define cost of a componet: minus a1 bridge and add cross componet edge
	global_min prioirty_queue inorder to get everything
		if the top of prioirty queue is not up to date (the cost is not the same) pop
		merge componet on the pop of priority queue, push the new one into prioirty_queue
		record the answer 
		repeat till added edge = 0
		the component's  union find set rrepresent it
	*/
	for(int i=0;i<m;i++){
		int u,v;cin>>u>>v;
		node* tempu = new node;
		tempu->prio = A[u]+A[v];
		tempu->u = u;
		tempu->v = v;
		R[u] = merge(R[u],tempu);
		node* tempv = new node;
		tempv->prio = A[u]+A[v];
		tempv->u = v;
		tempv->v = u;
		R[v] = merge(R[v],tempv);
	}
	for(int i=1;i<=n;i++){
		cost[i]	=  -(A[ONE]+A[i])+(R[i]->prio);
		pq.push({cost[i],i});
	}
	for(int i=n-2;i>=0;i--){
		pair<ll,int> cur = {-1,-1};
		while(pq.size()){
			cur = pq.top();
			pq.pop();
			if(taken[cur.second]) continue;
			if(cost[cur.second]!=cur.first) continue;
			break;
		}
		taken[cur.second]=1;
		ans[i] = ans[i+1]+cost[cur.second];
		int a = cur.second;
		int b = query(R[cur.second]->v);
		join(a,b);
		R[b] = merge(R[a],R[b]);
		while(get_size(R[b])){
			if(query(R[b]->u)==query(R[b]->v)) R[b] = pop(R[b]);
			else break;
		}
		ll prev = cost[b];
		if(!get_size(R[b])) cost[b] = 1e15;
		else cost[b] = -(A[ONE]+A[b])+(R[b]->prio);
		if(cost[b]!=prev){
			pq.push({cost[b],b});
		}
	}
	for(int i=0;i<=q;i++){
		cout<<ans[min(i,n-1)]+additional<<"\n";
	}
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...