• AT2534 港湾設備 (Port Facility)


    洛谷

    先膜一下Iscream巨巨

    首先我们可以把题目转化为线段覆盖,如果两条线段相交(不算某一条完全在另一条里面的情况),那么这两条线段代表的集装箱就不能放到同一个栈里,我们在它们之间连一条边。如果图里有奇环,那么说明无解。于是黑白染色,可以和食物链那个一样用并查集维护,如果有解,设连通块个数为(S),那么答案就是(2^S)

    然而线段很多,直接连边怕是要T飞。考虑如何维护线段相交,可以用一个栈,如果遇到线段的左端点就把它入栈,遇到右端点时就把左端点到栈顶的所有未出栈的线段都和它连边,然后把左端点弹出

    然而要在栈的中间弹出……小栈它可能做不太到……所以可以定义一个(nxt[i])表示(i)后面(包括自己)第一个没有出栈的元素,用一个类似并查集的方法乱搞就可以资瓷弹栈了

    然而相交的次数还是很多……考虑当前线段左端点和右端点间的这些线段要么颜色相等要么无解,所以可以用一个(jp[i])表示(i)后面下一个可能与它颜色不同的位置,每一次从左端点的下一位开始跳(jp)并暴力更改即可

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    const int N=2e6+5,P=1e9+7;
    int ksm(R int x,R int y){
    	R int res=1;
    	for(;y;y>>=1,x=1ll*x*x%P)if(y&1)res=1ll*res*x%P;
    	return res;
    }
    int fa[N],nxt[N],pos[N],st[N],w[N],jp[N];
    int n,top,ans,l,r,x,y,z;
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    int Nxt(int x){return nxt[x]==x?x:nxt[x]=Nxt(nxt[x]);}
    int add(R int x,R int y){
    	R int u=find(x),v=find(y),uu=find(x+n),vv=find(y+n);
    	if(u==v||uu==vv)return 0;
    	u<=vv?fa[vv]=u:fa[u]=vv;
    	v<=uu?fa[uu]=v:fa[v]=uu;
    	return 1;
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read();
    	fp(i,1,n)l=read(),r=read(),w[l]=w[r]=i;
    	fp(i,1,2*n)nxt[i]=fa[i]=i,jp[i]=i+1;
    	fp(i,1,2*n)if(!pos[w[i]])pos[w[i]]=++top,st[top]=w[i];
    	else{
    		x=pos[w[i]],y=Nxt(x+1);
    		while(y<=top){
    			if(!add(w[i],st[y]))return puts("0"),0;
    			z=jp[y],jp[y]=top+1,y=Nxt(z);
    		}nxt[x]=x+1;
    	}
    	fp(i,1,2*n)if(find(i)==i)++ans;
    	ans>>=1,ans=ksm(2,ans);printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    《易中天中华史》——易中天
    《易中天品三国》——易中天
    Excel 实现多列文本合并/合并单元格内容 的三种方法
    Excel函数OFFSET的用法、举例
    【转】链接服务器"(null)"的 OLE DB 访问接口 "Microsoft.Jet.OLEDB.4.0" 返回了消息 "未指定的错误"。+SQL Server Management Studio中访问EXCEL 2007(XLSX)文件的方法
    SQL 2005启用组件Ad Hoc Distributed Queries
    FTP 550 Permission denied 只能建文件夹,没法删除及上传文件的原因说明
    Access中"''80004005''"操作必须使用一个可更新的查询"错误的解决办法
    修改 打开方式为Excel
    VMware10新建虚拟机
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10171276.html
Copyright © 2020-2023  润新知