zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    FZU 2098 刻苦的小芳(卡特兰数,动态规划)
    卡特兰数总结
    FZU 1064 教授的测试(卡特兰数,递归)
    HDU 4745 Two Rabbits(区间DP,最长非连续回文子串)
    Java 第十一届 蓝桥杯 省模拟赛 正整数的摆动序列
    Java 第十一届 蓝桥杯 省模拟赛 反倍数
    Java 第十一届 蓝桥杯 省模拟赛 反倍数
    Java 第十一届 蓝桥杯 省模拟赛 反倍数
    Java 第十一届 蓝桥杯 省模拟赛 凯撒密码加密
    Java 第十一届 蓝桥杯 省模拟赛 凯撒密码加密
  • 原文地址:https://www.cnblogs.com/chdy/p/12919907.html
Copyright © 2011-2022 走看看