题目传送门

  唯一的传送门

题目大意

  给定$n$个串,每个串只包含 '','','?' ,其中 '?' 至多在每个串中出现1次,它可以被替换为 '' 或 '' 。问是否可能任意两个不同的串不满足一个是另一个的前缀。

  2-sat的是显然的。

  枚举每个通配符填0还是1,然后插入Trie树。

  对于Trie的每个点在2-sat中建点。

  如果其中一个点被选择,那么它祖先和所有后继的结束点都不能选。(然后逆否命题连边)

  对于一个包含通配符的串,通配符替换为0以及通配符替换为1的否命题等价,同样,通配符替换为1以及通配符替换为0的否命题等价(连双向边)。

  对于一个不包含通配符的串,直接它到的节点的从否命题节点连一条到它的有向边。

  于是我们得到边数平方的优秀做法。

  考虑前缀和优化,新建一个虚点表示Trie树上,它的祖先的命题都是假。但是这样还有点问题,还要建一个点表示Trie上,它的所有后继的命题都是假。

  建图比较繁杂,见下图:

  然后再说一下处理多个串在Trie树上共点。

  于是便有了点数$12n$的优秀做法。再由于代码常数巨大无比,成功Loj最慢榜榜首,sad。。。(一定要去学习一下榜首同学点数$4n$的优质做法)

Code

 /**
* loj.ac
* Problem#6036
* Accepted
* Time: 4346ms
* Memory: 469852k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; const int N = 5e5 + ; typedef class TrieNode {
public:
int id;
TrieNode* ch[];
vector<int> vs;
}TrieNode; TrieNode pool[N << ];
TrieNode* top = pool; TrieNode* newnode() {
top->id = ;
top->ch[] = top->ch[] = NULL;
return top++;
} typedef class Trie {
public:
TrieNode* rt; Trie():rt(newnode()) { } int insert(char* str, int id) {
TrieNode* p = rt;
for (int i = , c; str[i]; i++) {
c = str[i] - '';
if (!p->ch[c])
p->ch[c] = newnode();
p = p->ch[c];
}
if (!p->id)
p->id = id;
else if ((!p->vs.size() || p->vs[p->vs.size() - ] != id - ) && p->id != id - )
p->vs.push_back(id);
return p->id;
}
}Trie; int n, n2;
char buf1[N], buf2[N];
vector<int> g[N * ];
// 1 ~ 2 * n2 : Is the node seclected?
// 2 * n2 + 1 ~ 4 * n2: Aren't nodes above seclected?
// 4 * n2 + 1 ~ 6 * n2: Aren't nodes below seclected?
Trie tr; inline void init() {
scanf("%d", &n);
n2 = n << ;
for (int i = , len, p1, p2; i <= n; i++) {
scanf("%s", buf1);
len = strlen(buf1);
memcpy(buf2, buf1, len + );
for (int j = ; j < len; j++)
if (buf1[j] == '?')
buf1[j] = '';
for (int j = ; j < len; j++)
if (buf2[j] == '?')
buf2[j] = '';
p1 = tr.insert(buf1, (i << ) - );
p2 = tr.insert(buf2, i << );
if (p1 == p2) {
g[(i << ) - + n2].push_back((i << ) - );
} else {
p1 = ((i << ) - ), p2 = (i << );
g[p1].push_back(p2 + n2);
g[p2 + n2].push_back(p1);
g[p2].push_back(p1 + n2);
g[p1 + n2].push_back(p2);
}
}
} #define virt(_x) (_x + n2)
#define upre(_x) (_x + n2 * 2)
#define upvi(_x) (_x + n2 * 3)
#define dore(_x) (_x + n2 * 4)
#define dovi(_x) (_x + n2 * 5) void dfs(TrieNode* p, int last) {
if (!p) return;
if (p->vs.size()) {
vector<int> &ve = p->vs;
for (int i = ; i < (signed) ve.size(); i++) {
TrieNode* q = newnode();
q->id = ve[i];
q->ch[] = p->ch[], q->ch[] = p->ch[];
p->ch[] = NULL, p->ch[] = q;
}
ve.clear();
}
int id = p->id;
if (id) {
g[id].push_back(upvi(id));
g[id].push_back(dovi(id));
g[upre(id)].push_back(virt(id));
g[dore(id)].push_back(virt(id));
if (last) {
g[id].push_back(upre(last));
g[upvi(last)].push_back(virt(id));
g[last].push_back(dore(id));
g[dovi(id)].push_back(virt(last)); g[upre(id)].push_back(upre(last));
g[upvi(last)].push_back(upvi(id));
g[dore(last)].push_back(dore(id));
g[dovi(id)].push_back(dovi(last));
}
}
int nid = ((id) ? (id) : (last));
dfs(p->ch[], nid);
dfs(p->ch[], nid);
} int dfs_clock = ;
stack<int> st;
boolean vis[N * ], ins[N * ];
int dfn[N * ], low[N * ];
void tarjan(int p) {
vis[p] = true, ins[p] = true;
dfn[p] = low[p] = ++dfs_clock;
st.push(p);
for (int i = ; i < (signed) g[p].size(); i++) {
int e = g[p][i];
if (!vis[e]) {
tarjan(e);
low[p] = min(low[p], low[e]);
} else if (ins[e])
low[p] = min(low[p], dfn[e]);
} if (dfn[p] == low[p]) {
int cur;
do {
cur = st.top();
st.pop();
low[cur] = low[p];
ins[cur] = false;
} while (cur != p);
}
} void putans(const char* str) {
puts(str);
exit();
} inline void solve() {
dfs(tr.rt, );
for (int i = ; i <= n2 * ; i++)
if (!vis[i])
tarjan(i);
for (int i = ; i <= n2; i++) {
if (low[i] == low[virt(i)])
putans("NO");
if (low[upre(i)] == low[upvi(i)])
putans("NO");
if (low[dore(i)] == low[dovi(i)])
putans("NO");
}
putans("YES");
} int main() {
init();
solve();
return ;
}

Loj 6036 「雅礼集训 2017 Day4」编码 - 2-sat的更多相关文章

  1. LOJ #6036.「雅礼集训 2017 Day4」编码 Trie树上2-sat

    记得之前做过几道2-sat裸体,以及几道2-sat前缀优化建图,这道题使用了前缀树上前缀树优化建图.我们暴力建图肯定是n^2级别的,那么我们要是想让边数少点,就得使用一些骚操作.我们观察我们的限制条件 ...

  2. loj 6037 「雅礼集训 2017 Day4」猜数列 - 动态规划

    题目传送门 传送门 题目大意 有一个位置数列,给定$n$条线索,每条线索从某一个位置开始,一直向左或者向右走,每遇到一个还没有在线索中出现的数就将它加入线索,问最小的可能的数列长度. 依次从左到右考虑 ...

  3. LOJ #6037.「雅礼集训 2017 Day4」猜数列 状压dp

    这个题的搜索可以打到48分…… #include <cstdio> #include <cstring> #include <algorithm> ; bool m ...

  4. 2018.10.27 loj#6035. 「雅礼集训 2017 Day4」洗衣服(贪心+堆)

    传送门 显然的贪心题啊...考试没调出来10pts滚了妙的一啊 直接分别用堆贪心出洗完第iii件衣服需要的最少时间和晾完第iii件衣服需要的最少时间. 我们设第一个算出来的数组是aaa,第二个是bbb ...

  5. LOJ#6035. 「雅礼集训 2017 Day4」洗衣服

    传送门 先处理出每一件衣服最早什么时候洗完,堆+贪心即可 然后同样处理出每件衣服最早什么时候烘干 然后倒序相加取最大值 # include <bits/stdc++.h> using na ...

  6. LOJ #6035.「雅礼集训 2017 Day4」洗衣服 贪心

    这道题的贪心好迷啊~我们对于两个过程进行单独贪心,然后再翻转一个,把这两个拼起来.先说一下单独贪心,单独贪心的话就是用一个堆,每次取出最小的,并且把这个最小的加上他单次的,再放进去.这样,我们得到的结 ...

  7. 【LOJ6036】 「雅礼集训 2017 Day4」编码

    传送门 LOJ Solution 因为?只有两种可能为0,1,所以就把这两个串搞出来. 那么现在?取0和?取1不能并存,前缀不能并存,所以就是一个\(2-SAT\),现在问题在于这个东西可能会有很多条 ...

  8. [LOJ 6031]「雅礼集训 2017 Day1」字符串

    [LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...

  9. [LOJ 6030]「雅礼集训 2017 Day1」矩阵

    [LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...

随机推荐

  1. css 获取从第n个开始,之后的所有元素

    <div id="box"> <div></div> <div>等待获取</div> <div>等待获取&l ...

  2. Javaweb实现对mongodb的增删改查(附带源代码)

    运行截图: 删除后的信息 项目源代码:https://www.cnblogs.com/post/readauth?url=/zyt-bg/p/9807396.html

  3. Gym 102056L - Eventual … Journey - [分类讨论][The 2018 ICPC Asia-East Continent Final Problem L]

    题目链接:https://codeforces.com/gym/102056/problem/L LCR is really an incredible being. Thinking so, sit ...

  4. 转 docker创建私有仓库和k8s中使用私有镜像

    docker私有仓库建立 环境说明我们选取192.168.5.2做私有仓库地址yum install docker -y1.启动docker仓库端口服务 docker run -d -p 5000:5 ...

  5. 单片机小白应该如何学习stm32的一些实践心得!

    嵌入式搬砖道路上的大三狗一枚,撑死算个初学者吧.才学有限,下面仅仅是本人对STM32学习的一点心得与建议,希望对题主有帮助吧. 心得:本人当初学习STM32的时候有一些跟风的因素,自以为学的芯片越多就 ...

  6. HTTP Get Post究竟有哪些区别

    get在浏览器回退时是无害的,而post会再次提交请求. get产生的url地址可以被bookmark,而post不可以. get请求会被浏览器主动cache,而post不会,除非手动设置. get请 ...

  7. Win7-IE11 For x86&x64离线安装包

    一.Internet Explorer11简体中文版离线安装包:       微软已停止了IE11以下版本(包括IE10/9/8)的技术支持.以后Win7用IE11的机会也越来越多,但IE11官方安装 ...

  8. 17.3-uC/OS-III消息管理(消息队列使用)

    多值信号量和和互斥信号量主要用来标志事件是否发生和协调资源的访问.如果要给资源赋予内容进行传递, 信号量就力有所不及了.这时候就需要用到 uC/OS 操作系统的另一个内核机制了,那就是消息队列. 2. ...

  9. bugfree3.0.1-邮件配置

    系统内新建BUG或Case,或者BUG状态有修改时,这些操作都可以伴随邮件通知,提醒指派和抄送给对象及时关注. 配置方法 1.进入C:\xampp\htdocs\bugfree\protected\c ...

  10. docker容器与镜像

    就像cad图层概念 数据卷就是为了完成数据持久化操作