• 5.19 省选模拟赛 小B的图 最小生成树 LCT


    LINK:小B的图

    avatar
    avatar

    这道题就比较容易了。

    容易想到将询问离线 然后 从小到大排序 那么显然是优先放正图(x+k)的边。

    考虑随着x的增大 那么负图上的边会逐渐加进来 一条边被加进来当且仅当 其权值小于其能影响到的某条边的权值.

    这样 随便列一个不等式就可以解出下界.

    值得注意的是 加边的时候 肯定是x较小的先加 所以这个也要排序。

    一个需要证明的地方是:虽然x较小的先加 但事实上可能x较大的先加上去了.

    这个时候 是否会影响到x较小的加边情况呢?

    答案是否定的 考虑较大的可以先加进来 当且仅当 其影响到的边的权值更大 且较小的没有被影响到.

    那么加小的时候 和大的如果不存在交集那么无影响 如果存在交集那么判断的形态也不会改变 证毕.

    综上 可以利用LCT来维护这个过程 复杂度nlogn.

    值得注意的是 LCT维护的时候 一个比较简单的写法是 把边化点做.

    当然LCT本身有很多的细节 小心死循环...

    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 2100000000
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define gc(a) scanf("%s",a+1)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 1000000007
    #define S second
    #define F first
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define ull unsigned long long
    #define ui unsigned
    #define EPS 1e-8
    #define mod 998244353
    #define max(x,y) ((x)>(y)?(x):(y))
    #define sq sqrt
    #define IV inline void 
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        RE int x=0,f=1;RE char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const int MAXN=200010,maxn=500010;
    int n,Q,A,B,top,sum;ll ans,ans1[maxn];
    int fa[maxn];
    struct wy{int x,y,z;}t[maxn],g[maxn],w[maxn];
    inline int cmp(wy a,wy b){return a.z<b.z;}
    int f[maxn],mx[maxn],b[maxn],s[maxn],re[maxn],c[maxn][2];
    inline int getfather(int x){return x==fa[x]?fa[x]:fa[x]=getfather(fa[x]);}
    inline int pd(int x){return c[f[x]][1]==x||c[f[x]][0]==x;}
    IV reversal(int x)
    {
    	swap(c[x][0],c[x][1]);
    	re[x]^=1;
    }
    IV pushup(int x)
    {
    	mx[x]=x;
    	if(b[mx[c[x][0]]]>b[mx[c[x][1]]]){if(b[mx[c[x][0]]]>b[x])mx[x]=mx[c[x][0]];}
    	else if(b[mx[c[x][1]]]>b[x])mx[x]=mx[c[x][1]];
    }
    IV pushdown(int x)
    {
    	if(re[x])
    	{
    		if(c[x][0])reversal(c[x][0]);
    		if(c[x][1])reversal(c[x][1]);
    		re[x]=0;
    	}
    }
    IV rotate(int x)
    {
    	int old=f[x],oldf=f[old],k=c[old][1]==x;
    	c[old][k]=c[x][k^1];c[x][k^1]=old;
    	if(pd(old))c[oldf][c[oldf][1]==old]=x;
    	if(c[old][k])f[c[old][k]]=old;
    	f[x]=oldf;f[old]=x;pushup(old);
    }
    IV splay(int x)
    {
    	int y=x;top=0;
    	s[++top]=y;
    	while(pd(y))s[++top]=y=f[y];
    	while(top)pushdown(s[top--]);
    	while(pd(x))
    	{
    		int old=f[x],oldf=f[old];
    		if(pd(old))rotate(((c[old][1]==x)^(c[oldf][1]==old))?x:old);
    		rotate(x);
    	}
    	pushup(x);
    }
    IV access(int x)
    {
    	for(int y=0;x;x=f[y=x])
    		splay(x),c[x][1]=y,pushup(x);
    }
    IV make_root(int x)
    {
    	access(x);
    	splay(x);
    	reversal(x);
    }
    IV Link(int x,int y)
    {
    	make_root(x);
    	f[x]=y;
    }
    inline int ask(int x,int y)
    {
    	make_root(x);access(y);
    	splay(y);return mx[y];
    }
    IV cut(int x,int y)
    {
    	make_root(x);access(y);
    	splay(y);f[x]=c[y][0]=0;
    }
    int main()
    {
    	freopen("c.in","r",stdin);
    	freopen("c.out","w",stdout);
    	get(n);get(A);get(B);get(Q);
    	rep(1,A,i)
    	{
    		int get(x),get(y),get(z);
    		t[i]=(wy){x,y,z};
    	}
    	sort(t+1,t+1+A,cmp);
    	rep(1,B,i)
    	{
    		int get(x),get(y),get(z);
    		g[i]=(wy){x,y,z};
    	}
    	sort(g+1,g+1+B,cmp);b[0]=-INF-1;
    	rep(1,n,i)b[i]=-INF,fa[i]=i,mx[i]=i;
    	rep(1,A,i)b[i+n]=t[i].z,mx[i+n]=i+n;
    	rep(1,B,i)b[i+n+A]=-INF,mx[i+n+A]=i+n+A;
    	rep(1,A,i)
    	{
    		int xx=getfather(t[i].x);
    		int yy=getfather(t[i].y);
    		if(xx!=yy)
    		{
    			fa[xx]=yy;
    			Link(t[i].x,i+n);
    			Link(t[i].y,i+n);
    			ans+=t[i].z;
    		}
    	}
    	sum=n-1;
    	rep(1,B,i)//对于每个B求出v
    	{
    		int x=g[i].x;int y=g[i].y;
    		if(x==y){w[i].z=INF;w[i].x=0;continue;}
    		int ww=ask(x,y);
    		if(b[ww]==-INF){w[i].z=INF;w[i].x=0;continue;}
    		else
    		{
    			w[i].z=(g[i].z-b[ww]-1)/2+1;
    			w[i].x=b[ww];
    			w[i].y=g[i].z;
    			cut(t[ww-n].x,ww);
    			cut(t[ww-n].y,ww);
    			Link(x,i+n+A);
    			Link(y,i+n+A);
    		}
    	}
    	sort(w+1,w+1+B,cmp);
    	int flag=1;
    	rep(1,Q,j)t[j]=(wy){j,0,read()};
    	sort(t+1,t+1+Q,cmp);
    	rep(1,Q,j)
    	{
    		ll v=t[j].z;
    		while(w[flag].z<=v&&flag<=B)
    		{
    			--sum;ans-=w[flag].x;
    			ans+=w[flag].y;++flag;
    		}
    		ans1[t[j].x]=ans-(n-1-2*sum)*v;
    	}
    	rep(1,Q,i)putl(ans1[i]);
    	return 0;
    }
    
  • 相关阅读:
    学习linux之用户-文件-权限操作
    Hadoop--Hadoop的机架感知
    redhat 6.3 64位安装中文输入法全过程记录
    hdu 4619 Warm up 2(并查集)
    openGL 初试 绘制三角形 和添加鼠标键盘事件
    MySQL 启动服务报错解决方案
    20亿与20亿表关联优化方法(超级大表与超级大表join优化方法)
    50行python代码实现个代理server(你懂的)
    nginx+tomcat反复请求
    慢慢过渡到个人博客
  • 原文地址:https://www.cnblogs.com/chdy/p/12919907.html
Copyright © 2020-2023  润新知