小B的图( LCT维护最小生成树)

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
#define maxn 500005
#define inf 0x3f3f3f3f3f3f3f3fll
#define LL long long
using namespace std;

char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
template<class T>void read(T &res){
	char ch;bool f=0;
	for(;!isdigit(ch=getc());) if(ch=='-') f=-1;
	for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
	(f) && (res=-res);
}
int n,A,B,Q,tot;
int K[maxn],F[maxn];
int Find(int u){ return !F[u] ? u : F[u] = Find(F[u]); }
bool cmp(const int &u,const int &v){return K[u] < K[v]; }

int fa[maxn],ch[maxn][2],rev[maxn];
LL mx[maxn],mxp[maxn],vl[maxn];

#define pa fa[x]
int inr(int x){ return ch[pa][1] == x; }
int isr(int x){ return ch[pa][1] ^ x && ch[pa][0] ^ x; }
void dtp(int x){ if(x) rev[x]^=1,swap(ch[x][0],ch[x][1]); }
void dt(int x){ if(rev[x]) dtp(ch[x][0]),dtp(ch[x][1]),rev[x]=0; }
void dtpath(int x){ if(!isr(x)) dtpath(pa);dt(x); }
void upd(int x){ 
	mxp[x] = x , mx[x] = vl[x];
	if(mx[ch[x][0]] > mx[x]) mx[x] = mx[ch[x][0]] , mxp[x] = mxp[ch[x][0]];
	if(mx[ch[x][1]] > mx[x]) mx[x] = mx[ch[x][1]] , mxp[x] = mxp[ch[x][1]];
}
void rot(int x){
	int y = fa[x] , z = fa[y] , c = inr(x);
	if(!isr(y)) ch[z][inr(y)] = x;
	(ch[y][c] = ch[x][!c]) && (fa[ch[y][c]] = y);
	fa[fa[ch[x][!c]=y]=x]=z;
	upd(y);
}
void splay(int x){
	for(dtpath(x);!isr(x);rot(x))
		if(!isr(pa)) rot(inr(pa) ^ inr(x) ? x : pa);
	upd(x);
}
int access(int x){
	int y=0;
	for(;x;x=fa[y=x]){
		splay(x);
		ch[x][1] = y;
		upd(x);
	}
	return y;
}
void Bert(int x){
	access(x);
	splay(x);
	dtp(x);
}
void link(int u,int v){
	Bert(u),fa[u]=v;
}
void cut(int u,int v){
	Bert(u),access(v),splay(v);
	ch[v][0] = fa[u] = 0;
	upd(v);
}
LL ar[maxn],val[maxn],ans[maxn];
bool cmp2(const int &u,const int &v){ return val[u] < val[v]; }

int main(){
	
	freopen("3.in","r",stdin);
	freopen("3.out","w",stdout);
	
	read(n),read(A),read(B),read(Q);
	static int ux[maxn],vy[maxn],c[maxn],pt[maxn][2];
	for(int i=1;i<=A;i++)
		read(ux[i]),read(vy[i]),read(K[i]),c[i]=i;
	sort(c+1,c+1+A,cmp);
	for(int i=0;i<=n;i++) mx[i] = vl[i] = -inf;
	tot = n;
	LL sm = 0 , sz = 0;
	for(int i=1;i<=A;i++){
		int u = c[i];
		if(Find(ux[u]) != Find(vy[u])){
			F[Find(ux[u])] = Find(vy[u]);
			mx[++tot] = K[u] , vl[tot] = K[u] , mxp[tot] = tot;
			pt[tot][0] = ux[u] , pt[tot][1] = vy[u];
			link(ux[u] , tot);
			link(vy[u] , tot);
			sm += K[u] , sz ++;
		}
	}
	for(int i=1;i<=B;i++)
		read(ux[i]),read(vy[i]),read(K[i]),c[i]=i;
	sort(c+1,c+1+B,cmp);
	for(int i=1;i<=B;i++){
		int u = c[i];
		Bert(ux[u]) , access(vy[u]) , splay(vy[u]);
		if(mx[vy[u]] > -inf){
			int t = mxp[vy[u]];
			ar[++ar[0]] = K[u] - mx[vy[u]];
			cut(t,pt[t][0]),cut(t,pt[t][1]);
			link(ux[u],vy[u]);
		}
	}
	sort(ar+1,ar+1+ar[0]);
	for(int i=1;i<=Q;i++)
		read(val[i]),c[i]=i;
	sort(c+1,c+1+Q,cmp2);
	for(int i=1,j=1;i<=Q;i++){
		int u=c[i];
		for(;j<=ar[0] && ar[j] / 2.0 <= val[u];j++)
			sm += ar[j] , sz -= 2;
		ans[u] = sm + sz * val[u];
	}
	for(int i=1;i<=Q;i++)
		printf("%lld\n",ans[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值