zoukankan      html  css  js  c++  java
  • Jzoj5446 高考是不可能高考的

    Snuke 喜欢旗子.
    Snuke 正在将N 个旗子摆在一条线上.
    第i 个旗子可以被放在位置xi 或yi 上.

    Snuke 认为两个旗子间的最小距离越大越好. 请你求出最大值.


    今天这都是些集训队作业啊!

    这个题本来以为一眼能做结果死磕磕不动

    二分答案肯定是要的,问题是怎么判定解

    1.dp肯定不行了

    2.数据结构,也不行

    3.图的最大独立集,比较靠谱但是。。。复杂度爆炸

    正解:2SAT

    考完听他们说才恍然大悟,我在分析的时候漏掉了一个条件,重点都放在了"xi,yi只能选一个"

    但是还有一个条件:“xi,yi必须选一个”,我把这个重要条件作为判断二分可行性最后才用了

    说说怎么构图

    我们将所有的xi,yi放入一个数组s并排序,我们假设ai=0/1表示si这个位置有没有放旗子

    显然有两种边:

    1.若si和sj本来是同一个同一个k的xk,yk的话,这两者只可选择其一,即ai^aj=1

    2.|si-sj|<我们二分的Mid,那么这两者最多选一个即ai&aj=0

    很明显,如果直接暴力构图是过不去的,我们可以考虑以下两种优化方法:

    1.线段树优化连边

    2.分块优化连边

    具体思路就是建立一些辅助点,当一个点x向一片区间s[l,r]连边的时候不需要每个都连接而是通过辅助点,这样可以减少边的总数(类似于中转站)

    当然以上两种做法都比较复杂,我讲一种很简单而且很快的做法

    我们二分答案的时候,我们发现需要将r开得很大(10^9)

    而且我们注意到,如果暴力连边,Mid越大,边的数量就越多,而答案通常不大

    所以我们考虑尽量减少r来降低复杂度

    这里我们考虑一种dp的形式

    假设这个问题中,xi,yi可以同时取,那么这个问题就变成了一个在s上的动态规划

    方程为f[j]=max(f[i]+1){s[i]<=s[j]-Mid)

    那么显然,这样做出来的答案会比正确答案更优(但是不正确),但是不会脱离太远(平均情况下<=10Answer)

    所以我们将其作为一个二分的上界不会出问题只会优化时间复杂度

    让后就莫名其妙拿了rank5[>_<]!

    #include<vector>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 10010
    using namespace std;
    struct Graph{
    	vector<int> G[N<<2];
    	int dfn[N<<2],low[N<<2],stk[N<<2],top;
    	int cnt,col[N<<2],clk,Col;
    	inline void clear(int m){ 
    		cnt=top=clk=Col=0; 
    		for(int i=1;i<=m;++i) G[i].clear();
    		memset(dfn,0,sizeof dfn);
    		memset(col,0,sizeof col);
    	}
    	inline void adj(int x,int y){ G[x].push_back(y); }
    	void dfs(int x){
    		dfn[x]=low[x]=++clk;
    		stk[++top]=x;
    		for(int v,i=0,z=G[x].size();i<z;++i)
    			if(!dfn[v=G[x][i]]){
    				dfs(v); low[x]=min(low[x],low[v]);
    			} else if(!col[v]) low[x]=min(dfn[v],low[x]);
    		if(low[x]==dfn[x]){
    			++Col;
    			do{ col[stk[top]]=Col; } while(stk[top--]!=x);
    		}
    	}
    	bool gScn(int n){
    		for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i);
    		n>>=1;
    		for(int i=1;i<=n;++i) if(col[i]==col[i+n]) return 0;
    		return 1;
    	}
    } G;
    struct dt{ int v,r; } s[N<<1];
    int x[N],y[N],p[N<<1],n,m=0,c[N];
    inline bool c1(dt a,dt b){ return a.v<b.v; }
    inline int lowerbound(int p,int k){
    	int l=1,r=p;
    	for(int M;l<r;){
    		M=l+r>>1;
    		if(s[M].v<=k) l=M+1;
    		else r=M;
    	}
    	return l;
    }
    inline int upperbound(int p,int k){
    	int l=p,r=m;
    	for(int M;l<r;){
    		M=l+r+1>>1;
    		if(s[M].v>=k) r=M-1;
    		else l=M;
    	}
    	return l;
    }
    void buildGraph(int x){
    	G.clear(m<<1);
    	for(int i=1;i<=m;++i) G.adj(i,p[i]+m),G.adj(i+m,p[i]);
    	for(int l,r,i=1;i<=m;++i){
    		l=lowerbound(i,s[i].v-x);
    		r=upperbound(i,s[i].v+x);
    		for(;l<i;++l) G.adj(i,l+m);
    		for(;r>i;--r) G.adj(i,r+m);
    	}
    }
    int v[N<<1],f[N<<1];
    inline bool ok(int x){
    	v[0]=-100000000;
    	memset(f,0,sizeof f); f[0]=0;
    	for(int i=1,j;i<=m;++i){
    		j=lower_bound(v,v+1+m,v[i]-x)-v;
    		while(v[j]>v[i]-x) --j;
    		f[i]=max(f[i-1],f[j]+1);
    	}
    	return f[m]>=n;
    }
    int main(){
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%d%d",x+i,y+i);
    		s[++m]=(dt){x[i],i};
    		s[++m]=(dt){y[i],i};
    	}
    	sort(s+1,s+1+m,c1);
    	for(int i=1;i<=m;++i){
    		v[i]=s[i].v;
    		if(!c[s[i].r]) c[s[i].r]=i;
    		else { p[c[s[i].r]]=i; p[i]=c[s[i].r]; }
    	}
    	int l=0,r=100000000;
    	for(int M;l<r;){
    		M=l+r+1>>1;
    		if(ok(M)) l=M;
    		else r=M-1;
    	}
    	l=0;
    	for(int M;l<r;){
    		M=l+r+1>>1;
    		buildGraph(M);
    		if(G.gScn(m<<1)) l=M;
    		else r=M-1;
    	}
    	printf("%d
    ",l);
    }

  • 相关阅读:
    如何使用BackgroundWorker
    Start SQL Service failed with message: "the log scan number passed to log scan in database 'master' is not valid"
    Cmdkey 凭证管理器工具
    PowerShell根据下载link下载文件
    vnc远程到连接linux服务器。
    shell远程取数据的脚本.
    about开源监控nagios.
    Android入门:File文件存储
    Android入门:Layout
    Android入门:Log介绍
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/7800614.html
Copyright © 2011-2022 走看看