zoukankan      html  css  js  c++  java
  • IOI2021集训队作业154BE Evolution in Parallel

    (n+1)个字符串。如果(s_i)(s_j)的子序列,则连边((j,i))

    现在要求找到两条路径,使得它们只在(0)处相交,并且覆盖所有点。

    (nle 4000)


    哇哈为什么我想到了dilworth引理……

    先按照长度排序,然后维护两条链的链尾,设为(a,b)

    如果((i,a)in E)((i,b)in E)只满足一个,则直接接在后面。

    如果都不满足则无解。

    如果都满足,则搞一个(c=i),暂时把两条链合成一条链。后面接着做,如果能接在这条链后面则接;如果不能接,就把它丢到(a)(b)后面,然后(c)接在另一条的后面,于是又分开为两条链。(在这个局面之后链尾分别为(i)(i-1),并且没有其它方法使得构造后链尾不为(i)(i-1),相当于把问题划分成前后两部分。)


    using namespace std;
    #include <bits/stdc++.h>
    #define N 4005
    void imp(){
    	printf("impossible
    ");
    	exit(0);
    }
    int n;
    char str[N][N];
    int s[N][N],t[N][N][3];
    int len[N];
    int q[N];
    bool cmpq(int x,int y){return len[x]<len[y];}
    void init(int i,char str[]){
    	int m=len[i]=strlen(str+1);
    	t[i][m+1][0]=t[i][m+1][1]=t[i][m+1][2]=m+1;
    	for (int j=m;j>=1;--j){
    		s[i][j]=(str[j]=='A'?0:str[j]=='C'?1:2);
    		memcpy(t[i][j],t[i][j+1],sizeof t[i][j]);
    		t[i][j][s[i][j+1]]=j+1;
    	}
    	memcpy(t[i][0],t[i][1],sizeof t[i][0]);
    	t[i][0][s[i][1]]=1;
    }
    bool sub(int u,int v){
    	int x=0;
    	for (int i=1;i<=len[u];++i){
    		x=t[v][x][s[u][i]];
    		if (x>len[v])
    			return 0;
    	}
    	return 1;
    }
    int f[N];
    int main(){
    //	freopen("in.txt","r",stdin);
    	scanf("%d",&n);
    	scanf("%s",str[n+1]+1),len[n+1]=strlen(str[n+1]+1);
    	for (int i=1;i<=n;++i)	
    		scanf("%s",str[i]+1),len[i]=strlen(str[i]+1);
    	for (int i=1;i<=n;++i)	
    		q[i]=i;
    	sort(q+1,q+n+1,cmpq);
    	init(n+1,str[n+1]);
    	for (int i=1;i<=n;++i)
    		init(i,str[q[i]]);
    	if (!sub(n,n+1))
    		imp();
    	f[n]=n+1;
    	int a=n,b=n+1,c=0;
    	for (int i=n-1;i>=1;--i){
    		if (c){
    			if (sub(i,i+1))
    				f[i]=i+1;
    			else{
    				if (sub(i,a))
    					f[i]=a,f[c]=b;
    				else if (sub(i,b))
    					f[i]=b,f[c]=a;
    				else
    					imp();
    				a=i+1,b=i;
    				c=0;
    			}
    		}
    		else{
    			if (sub(i,a)){
    				if (sub(i,b))
    					c=i;
    				else
    					f[i]=a,a=i;
    			}
    			else if (sub(i,b))
    				f[i]=b,b=i;
    			else
    				imp();
    		}
    	}
    	if (c)
    		f[c]=a;
    	static bool bz[N];
    	int cnt0=0;
    	for (int x=1;x<=n;x=f[x])
    		bz[x]=1,cnt0++;
    	printf("%d %d
    ",cnt0,n-cnt0);
    	for (int i=1;i<=n;++i)
    		if (bz[i])
    			printf("%s
    ",str[q[i]]+1);
    	for (int i=1;i<=n;++i)
    		if (!bz[i])
    			printf("%s
    ",str[q[i]]+1);
    	return 0;
    }
    
  • 相关阅读:
    wpf passwordbox控件 光标移到最后
    C#程序 给IE网页IFRAME控件中所嵌入网页的元素赋值
    C#客户端填充外部IE浏览器中网页文本(input)且不提交
    C# 获取当前网页HTML
    WPF 带有提示文本的透明文本框
    C# 导出Excel文件 所导出文件打开时提示“Excel文件格式与扩展名指定格式不一致”
    php生成验证码
    Python命名规范
    UE4碰撞规则详解
    四大编程思想简述
  • 原文地址:https://www.cnblogs.com/jz-597/p/14471185.html
Copyright © 2011-2022 走看看