zoukankan      html  css  js  c++  java
  • 【YbtOJ#608】前缀编码

    题目

    题目链接:https://www.ybtoj.com.cn/contest/127/problem/1

    (n,sum|S|leq 5 imes 10^5)

    思路

    由于每一个 ? 只能填 (0)(1),不难想到 2-sat。
    将串安装长度排序,把每一个 ? 分别当作 (0)(1) 一次扔进一棵 Trie 中,Trie 上每一个节点维护以该节点结尾的字符串集合。走到一个点时将现在的字符串与该节点的集合中的字符串连边,注意一个字符串需要区分 ?(0)(1)
    然后跑 2-sat 即可。
    但是这样的空间复杂度是 (O(n^2)) 的。不可以接受。我们发现如果空间需要卡满 (O(n^2)),那么短串一定多,这会导致答案为 NO。所以我们每插入 lim 个串就跑一次 tarjan,如果已经无解了就输出 NO 即可。我取 (lim=1000)
    说白了就是一个乱搞,实际上有时空严格 (O(n+m)) 的做法。

    代码

    #include <bits/stdc++.h>
    #define mp make_pair
    #define NOT(x) ((x>m)?(x-m):(x+m))
    using namespace std;
    
    const int N=1000010,M=20000010;
    int n,m,tot,cnt,head[N],dfn[N],low[N],col[N];
    char s[N],t[N];
    bool vis[N];
    stack<int> st;
    
    struct node
    {
    	int pos,len,p;
    }b[N];
    
    struct edge
    {
    	int next,to;
    }e[M];
    
    void add(int from,int to)
    {
    	e[++tot]=(edge){head[from],to};
    	head[from]=tot;
    }
    
    bool cmp(node x,node y)
    {
    	return x.len<y.len;
    }
    
    struct Trie
    {
    	int tot,ch[N][2];
    	vector<int> end[N];
    	Trie() { tot=1; }
    	
    	bool ins(int l,int r,int k)
    	{
    		int p=1;
    		for (int i=l;i<=r;i++)
    		{
    			int id=s[i]-48;
    			if (!ch[p][id]) ch[p][id]=++tot;
    			p=ch[p][id];
    			for (int j=0;j<end[p].size();j++)
    				add(end[p][j],NOT(k)),add(k,NOT(end[p][j]));
    		}
    		end[p].push_back(k);
    		return 0;
    	}
    }trie;
    
    void tarjan(int x)
    {
    	dfn[x]=low[x]=++cnt;
    	st.push(x); vis[x]=1;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if (!dfn[v])
    		{
    			tarjan(v);
    			low[x]=min(low[x],low[v]);
    		}
    		else if (vis[v])
    			low[x]=min(low[x],dfn[v]);
    	}
    	if (low[x]>=dfn[x])
    	{
    		int y; n++;
    		do {
    			y=st.top(); st.pop();
    			col[y]=n; vis[y]=0;
    		} while (x!=y);
    	}
    }
    
    int main()
    {
    	freopen("code.in","r",stdin);
    	freopen("code.out","w",stdout);
    //	return printf("%d
    ",sizeof(e)/1024/1024),0;
    	memset(head,-1,sizeof(head));
    	scanf("%d",&m);
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%s",t);
    		b[i]=(node){n+1,(int)strlen(t),0};
    		for (int j=0;j<b[i].len;j++)
    		{
    			s[++n]=t[j];
    			if (s[n]=='?') b[i].p=n;
    		}
    	}
    	sort(b+1,b+1+m,cmp);
    	for (int i=1;i<=m;i++)
    	{
    		if (b[i].p)
    		{
    			s[b[i].p]='0';
    			if (trie.ins(b[i].pos,b[i].pos+b[i].len-1,i))
    				return printf("NO"),0;
    			s[b[i].p]='1';
    			if (trie.ins(b[i].pos,b[i].pos+b[i].len-1,i+m))
    				return printf("NO"),0;
    		}
    		else
    		{
    			int id=i+(s[b[i].pos]-48)*m;
    			if (trie.ins(b[i].pos,b[i].pos+b[i].len-1,id))
    				return printf("NO"),0;
    			if (s[b[i].pos]==48) add(i+m,i);
    			if (s[b[i].pos]==49) add(i,i+m);
    		}
    		if (i%1000==0)
    		{
    			cnt=n=0;
    			for (int j=1;j<=i;j++)
    				if (!dfn[j]) tarjan(j);
    			for (int j=1;j<=i;j++)
    				if (col[j]==col[j+m])
    					return printf("NO"),0;
    			for (int j=1;j<=i;j++)
    				col[j]=dfn[j]=col[j+m]=dfn[j+m]=0;
    		}
    	}
    	cnt=n=0;
    	for (int i=1;i<=m;i++)
    		if (!dfn[i]) tarjan(i);
    	for (int i=1;i<=m;i++)
    		if (col[i]==col[i+m])
    			return printf("NO"),0;
    	printf("YES");
    	return 0;
    }
    
    
  • 相关阅读:
    判断具有某个属性js、jQuery
    新建maven项目,JRE System Library[J2SE-1.5]
    maven多模块搭建
    The POM for * is invalid
    【react】react-bookManager
    【cml】wosi-demo
    关于白盒测试
    【weex】h5weex-example
    【weex】publishTask
    Eslint报错的翻译
  • 原文地址:https://www.cnblogs.com/stoorz/p/14459785.html
Copyright © 2011-2022 走看看