zoukankan      html  css  js  c++  java
  • 【JZOJ5433】图

    description

    有一个n个点A+B条边的无向连通图,有一变量x,每条边的权值都是一个关于x的简单多项式,其中有A条边的权值是k+x,另外B条边的权值是k-x,如果只保留权值形如k+x的边,那么这个图仍是一个连通图,如果只保留权值形如k-x的边,这个图也依然是一个连通图。
    给出q组询问,每组询问给出x的值,问此时这个无向连通图的最小生成树权值是多少。


    analysis

    • 首先容易知道图任意时候的(MST)只由(A)集合或(B)集合内的边组成

    • (x)(-∞)逐渐变为(+∞)(MST)会从只由(A)的边构成逐渐变成只由(B)的边构成

    • 这里(MST)只会变化(n-1)次,那么用(LCT)维护(MST)的添边删边

    • 当然先(kruskal)(A)(B)各有用的(n-1)条边搞出来,把(A)的边塞到(LCT)上面

    • 升序排序(B)的边一条条加进(LCT)里面,然后代替掉新环里(k)最大的(A)

    • 用当前(B)边的(k-x)减去删去该(A)边的(k+x),会得到(k'-2x)一类式子

    • 注意如果查询的环边上有(B)边,因为只换掉(A)边无视(B)边,所以连(B)边时不用连边节点

    • 如果有多条(B)边,由于升序加入(LCT),所以(k)更小的(B)边会贡献得早

    • 对于最后的求答案,把询问排序,且已经得到(n-1)(k-2x)这样的式子

    • 把式子再按(k)排序,看每个询问会用到前替换的多少条边(也就是前多少条式子)

    • 扫一遍这堆式子,只要(k-2*)当前询问的数(<=0),说明替换这条边是有贡献的,继续扫下去

    • 注意答案还要算上每个(k)以及剩下还没有被替换的(A)边里的(+x)


    code

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define MAXN 500005
    #define ha 1926081719491001
    #define ll long long
    #define reg register ll
    #define fo(i,a,b) for (reg i=a;i<=b;++i)
    #define fd(i,a,b) for (reg i=a;i>=b;--i)
    
    using namespace std;
    
    ll tr[MAXN][2],fa[MAXN],pf[MAXN],st[MAXN],fat[MAXN],val[MAXN],answer[MAXN];
    ll n,m,A,B,q,tot,cnt,ans;
    struct quiry{ll x,y;}inquiry[MAXN];
    struct edge{ll x,y,z;}f[2][MAXN],g[MAXN];
    struct node{ll mx,val,size;bool rev;}a[MAXN];
    inline ll read(){ll x=0,f=1;char ch=getchar();while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
    inline void swap(ll &x,ll &y){ll z=x;x=y,y=z;}
    inline bool cmp(edge a,edge b){return a.z<b.z;}
    inline bool cmpp(quiry a,quiry b){return a.x<b.x;}
    inline ll getfa(ll x){return !fat[x]?x:fat[x]=getfa(fat[x]);}
    inline void update(ll x){if (!x)return;a[x].mx=x;if (a[a[tr[x][0]].mx].val>a[a[x].mx].val)a[x].mx=a[tr[x][0]].mx;if (a[a[tr[x][1]].mx].val>a[a[x].mx].val)a[x].mx=a[tr[x][1]].mx;a[x].size=a[tr[x][0]].size+a[tr[x][1]].size+1;}
    inline void reverse(ll x){if (x)swap(tr[x][0],tr[x][1]),a[x].rev^=1;}
    inline void down(ll x){if (a[x].rev)reverse(tr[x][0]),reverse(tr[x][1]),a[x].rev=0;}
    inline void downdata(ll x){while (x)st[++st[0]]=x,x=fa[x];while (st[0])down(st[st[0]--]);}
    inline ll lr(ll x){return tr[fa[x]][1]==x;}
    inline void rotate(ll x){ll y=fa[x],k=lr(x);tr[y][k]=tr[x][!k];if (tr[x][!k])fa[tr[x][!k]]=y;fa[x]=fa[y];if (fa[y])tr[fa[y]][lr(y)]=x;tr[x][!k]=y,fa[y]=x,pf[x]=pf[y],update(y),update(x);}
    inline void splay(ll x,ll y){downdata(x);while (fa[x]!=y){if (fa[fa[x]]!=y)rotate(lr(fa[x])==lr(x)?fa[x]:x);rotate(x);}}
    inline void access(ll x){for (ll y=0;x;update(x),y=x,x=pf[x])splay(x,0),fa[tr[x][1]]=0,pf[tr[x][1]]=x,tr[x][1]=y,fa[y]=x,pf[y]=0;}
    inline void makeroot(ll x){access(x),splay(x,0),reverse(x);}
    inline void link(ll x,ll y){makeroot(x),pf[x]=y;}
    inline void cut(ll x,ll y){makeroot(x),access(y),splay(x,0),tr[x][1]=fa[y]=pf[y]=0,update(x);}
    inline ll query(ll x,ll y){makeroot(x),access(y),splay(y,0);return a[y].mx;}
    int main()
    {
    	freopen("T3.in","r",stdin);
    	//freopen("graph.in","r",stdin);
    	//freopen("graph.out","w",stdout);
    	n=read(),A=read(),B=read(),q=read();
    	fo(i,1,A)f[0][i].x=read(),f[0][i].y=read(),f[0][i].z=read();
    	fo(i,1,B)f[1][i].x=read(),f[1][i].y=read(),f[1][i].z=read();
    	sort(f[0]+1,f[0]+A+1,cmp),sort(f[1]+1,f[1]+B+1,cmp);
    	fo(i,0,n)a[i].val=-ha;
    	fo(i,1,A)
    	{
    		ll x=f[0][i].x,y=f[0][i].y,z=f[0][i].z;
    		if (getfa(x)!=getfa(y))fat[getfa(x)]=getfa(y),ans+=z,
    		a[n+i].val=z,a[n+i].mx=n+i,link(x,n+i),link(n+i,y);
    	}
    	memset(fat,0,sizeof(fat));
    	fo(i,1,B)
    	{
    		ll x=f[1][i].x,y=f[1][i].y,z=f[1][i].z;
    		if (getfa(x)!=getfa(y))fat[getfa(x)]=getfa(y),g[++tot]=f[1][i];
    	}
    	fo(i,1,tot)
    	{
    		ll x=g[i].x,y=g[i].y,z=g[i].z,tmp=query(x,y);
    		if (tmp<=n)continue;
    		cut(f[0][tmp-n].x,tmp),cut(tmp,f[0][tmp-n].y);
    		link(x,y),val[++cnt]=z-a[tmp].val;
    	}
    	fo(i,1,q)inquiry[i].x=read(),inquiry[i].y=i;
    	sort(inquiry+1,inquiry+q+1,cmpp),sort(val+1,val+cnt+1);
    	fo(i,1,q)
    	{
    		while (m<tot && val[m+1]<=inquiry[i].x*2)ans+=val[++m];
    		answer[inquiry[i].y]=ans+inquiry[i].x*(n-m*2-1);
    	}
    	fo(i,1,q)printf("%lld
    ",answer[i]);
    	return 0;
    }
    
  • 相关阅读:
    Mvc+三层(批量添加、删除、修改)
    js中判断复选款是否选中
    EF的优缺点
    Git tricks: Unstaging files
    Using Git Submodules
    English Learning
    wix xslt for adding node
    The breakpoint will not currently be hit. No symbols have been loaded for this document."
    Use XSLT in wix
    mfc110ud.dll not found
  • 原文地址:https://www.cnblogs.com/horizonwd/p/11600131.html
Copyright © 2011-2022 走看看