AFO

小B的图

C

首先A和B序列自己的顺序是不会变的,但是相对顺序会随着x改变

把x排序,顺着考虑

如果x为-inf那么答案就是A的最小生成树

然后按照B的顺序尝试把边加到MST里,LCT维护边(每条边开一个节点),得到B能代替这条边的最小v,存进答案里

可以感性理解这样是对的(

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define LL long long 
#define flip(x) swap(c[x][0],c[x][1]), ft[x]^=1
#define ind(x) (x==c[f[x]][1])
#define ir(x) (c[f[x]][0]==x || c[f[x]][1]==x)
using namespace std;

const int M = 500001;
int n,m,k,F[M],A,B;
LL ans[M];
struct Q
{
	int id,v;
} q[M];

struct vv
{
	int x,y,k;
} a[M],b[M];
vector<pair<int,int> > v;

int ff(int x)
{
	if(F[x]==x) return x;
	return F[x]=ff(F[x]);
}

bool cmp(vv a,vv b){return a.k<b.k;}
bool Cmp(Q a, Q b) {return a.v<b.v;}
int c[M][2],rt,f[M],h[M],tag[M],ft[M],d[M],fr[M],z[M];


void update(int x)
{
	d[x]=z[x], fr[x]=x;
	if(c[x][0] && d[c[x][0]]>d[x]) d[x]=d[c[x][0]], fr[x]=fr[c[x][0]];
	if(c[x][1] && d[c[x][1]]>d[x]) d[x]=d[c[x][1]], fr[x]=fr[c[x][1]];
}

void pd(int x)
{
	if(!ft[x])  return;
	if(c[x][0]) flip(c[x][0]);
	if(c[x][1]) flip(c[x][1]);
	ft[x]=0;
}

void rot(int x)
{
	int y=f[x], z=f[y], m1=ind(x), m2=ind(y), C=c[x][!m1];
	if(ir(y)) c[z][m2]=x; c[x][!m1]=y, c[y][m1]=C;
	if(C) f[C]=y; f[x]=z, f[y]=x;
	update(y), update(x); 
}

void splay(int x)
{
	int t=1, y=x; h[1]=x;
	while(ir(y)) h[++t]=y=f[y];
	while(t) pd(h[t--]);
	while(ir(x))
	{
		if(ir(f[x])) ind(f[x])==ind(x) ? rot(f[x]) : rot(x);
		rot(x);
	} 
	update(x);
}

void access(int x)
{
	for(int y=0;x;x=f[y=x])
	{
		splay(x); c[x][1]=y; update(x);
	}
}

void mr(int x)
{
	access(x); splay(x); flip(x);
}

int Fr(int x)
{
	access(x); splay(x);
	while(c[x][0]) pd(x), x=c[x][0];
	return x;
}

void split(int x,int y)
{
	mr(x); access(y); splay(y);
}

void link(int x,int y)
{
	mr(x); if(Fr(y)!=x) f[x]=y;
}

void cut(int x,int y)
{
	split(x,y); 
	if(Fr(y)==x && !c[x][1] && f[x]==y) f[x]=c[y][0]=0, update(y); 
}

int main()
{
	scanf("%d%d%d%d",&n,&A,&B,&m);
	for(int i=1;i<=A;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].k);
	sort(a+1,a+1+A,cmp);
	for(int i=1;i<=B;i++) scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].k);
	sort(b+1,b+1+B,cmp);
	for(int i=1;i<=n;i++) 
	{
		z[i]=d[i]=-0x3f3f3f3f; fr[i]=i;
		F[i]=i; 
	}
	LL s=0;
	for(int i=1;i<=A;i++) if(ff(a[i].x)!=ff(a[i].y))
	{
		z[i+n]=d[i+n]=a[i].k; fr[i+n]=i+n;
		link(i+n,a[i].x);
		link(i+n,a[i].y);
		F[F[a[i].x]]=F[a[i].y];
		s+=a[i].k;
	}
	for(int i=1;i<=B;i++)
	{
		split(b[i].x,b[i].y);
		if(fr[b[i].y]<=n) continue;
		int w=(b[i].k-d[b[i].y]+1)/2;
		v.push_back({w,b[i].k-d[b[i].y]});
		int t=fr[b[i].y];
		cut(t,a[t-n].x);
		cut(t,a[t-n].y);
		link(b[i].x,b[i].y);
	}
	sort(v.begin(), v.end());
	for(int i=1;i<=m;i++) scanf("%d",&q[i].v), q[i].id=i;

	sort(q+1,q+1+m,Cmp);
	int t=0, g=0; 
	
	for(int i=1;i<=m;i++)
	{
		while(t<v.size() && v[t].first<=q[i].v) s+=v[t].second, g++, t++;
		ans[q[i].id]=(n-1ll-t-t)*q[i].v+s;
	}
	for(int i=1;i<=m;i++) printf("%lld\n",ans[i]); 
}
posted @ 2020-05-20 20:35  ZUTTER☮  阅读(292)  评论(0编辑  收藏  举报