• [Contest on 2020.12.1] ZZH的游戏


    ( ext{Description})

    传送门

    ( ext{Solution})

    可以先考虑二分一个答案,发现可以先固定一个端点,另一个点拓展与它相连通的小于等于那个点的点,然后更新另一个点连通块的最小值,再用先开始的端点拓展…当无法拓展且需要新加入的点与另一边的最小值点相加大于二分的答案,而且两边的 (1) 都没被包含就不合法,这个过程可以用堆来维护,时间复杂度 (mathcal O(nlog ^2n))

    其实可以省掉二分,我们把初始答案设为 (s+t),按上面的方法直接拓展即可。时间复杂度 (mathcal O(nlog n))

    其实也可以省掉堆,因为这个题目有一个性质:权值是连续的 ([1,n]) 区间内的数。

    对于每一个点我们有两个标记:(vis,in),分别表示旁边是否已经有进块的点,是否在连通块。一边找到最小值后,其实不用直接赋值,可以将最小值线一步步下挪,将另一边的最大值线一步步上挪,尝试拓展最大值线代表的点入块,这样就是 (mathcal O(n)) 的?

    ( ext{Code})

    #include <cstdio>
    
    #define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
    #define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
    #define print(x,y) write(x),putchar(y)
    
    template <class T> inline T read(const T sample) {
        T x=0; int f=1; char s;
        while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
        while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
        return x*f;
    }
    template <class T> inline void write(const T x) {
        if(x<0) return (void) (putchar('-'),write(-x));
        if(x>9) write(x/10);
        putchar(x%10^48);
    }
    
    const int maxn=1e6+5;
    
    int n,lim[2],ans,s,t,lims,limt,mins,mint;
    bool vis[maxn][2],In[maxn][2];
    int cnt[2],head[maxn][2],nxt[maxn<<1][2],to[maxn<<1][2];
    
    void addEdge(int u,int v,bool op) {
    	nxt[++cnt[op]][op]=head[u][op],to[cnt[op]][op]=v,head[u][op]=cnt[op];
    	nxt[++cnt[op]][op]=head[v][op],to[cnt[op]][op]=u,head[v][op]=cnt[op];
    }
    
    void dfss(int u) {
    	In[u][0]=1;
    	if(u<mins) mins=u;
    	for(int i=head[u][0];i;i=nxt[i][0]) {
    		int v=to[i][0];
    		if(!In[v][0]) {
    			if(lims<v) vis[v][0]=1;
    			else dfss(v);
    		}
    	}
    }
    
    void dfst(int u) {
    	In[u][1]=1;
    	if(u<mint) mint=u;
    	for(int i=head[u][1];i;i=nxt[i][1]) {
    		int v=to[i][1];
    		if(!In[v][1]) {
    			if(limt<v) vis[v][1]=1;
    			else dfst(v);
    		}
    	}
    }
    
    int main() {
    	int u,v;
    	for(int T=read(9);T;--T) {
    		n=read(9); cnt[0]=cnt[1]=0;
    		for(int i=1;i<=n;++i) head[i][0]=head[i][1]=In[i][0]=In[i][1]=vis[i][0]=vis[i][1]=0;
    		for(int i=1;i<n;++i) u=read(9),v=read(9),addEdge(u,v,0);
    		for(int i=1;i<n;++i) u=read(9),v=read(9),addEdge(u,v,1);
    		s=read(9),t=read(9); lims=mins=s,mint=limt=t;
    		vis[s][0]=vis[t][1]=1; ans=s+t;
    		while(233) {
    			if(lims<=n&&vis[lims][0]&&(!In[lims][0])) dfss(lims);
    			if(limt<=n&&vis[limt][1]&&(!In[limt][1])) dfst(limt);
    			if(s==mins&&t==mint) break;
    			if(s>mins) --s,++limt;
    			if(t>mint) --t,++lims;
    		}
    		while(!In[1][0]||In[1][1]==0) {
    			++ans; ++lims,++limt;
    			while(233) {
    				if(lims<=n&&vis[lims][0]&&(!In[lims][0])) dfss(lims);
    				if(limt<=n&&vis[limt][1]&&(!In[limt][1])) dfst(limt);
    				if(s==mins&&t==mint) break;
    				if(s>mins) --s,++limt;
    				if(t>mint) --t,++lims;
    			}
    		}
    		print(ans,'
    ');
    	}
    	return 0;
    } 
    
  • 相关阅读:
    [A类会议] 国内论文检索
    [NISPA类会议] 怎样才能在NIPS 上面发论文?
    [国际A类会议] 2018最最最顶级的人工智能国际峰会汇总!CCF推荐!
    [DEFCON全球黑客大会] 针对CTF,大家都是怎么训练的?
    [DEFCON全球黑客大会] CTF(Capture The Flag)
    推荐系统之--- 评分预测问题
    推荐系统之--- 推荐系统实例
    推荐系统学习 -- 利用社交网络数据
    推荐系统学习 -- 利用上下文信息
    推荐系统学习 -- 利用用户标签数据
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/14069789.html
Copyright © 2020-2023  润新知