小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]);
}