• Loj 6036 「雅礼集训 2017 Day4」编码


    题目传送门

      唯一的传送门

    题目大意

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

      2-sat的是显然的。

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

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

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

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

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

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

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

      建图比较繁杂,见下图:

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

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

    Code

      1 /**
      2  * loj.ac
      3  * Problem#6036
      4  * Accepted
      5  * Time: 4346ms
      6  * Memory: 469852k
      7  */ 
      8 #include <bits/stdc++.h>
      9 using namespace std;
     10 typedef bool boolean;
     11 
     12 const int N = 5e5 + 5;
     13 
     14 typedef class TrieNode {
     15     public:
     16         int id;
     17         TrieNode* ch[2];
     18         vector<int> vs;
     19 }TrieNode;
     20 
     21 TrieNode pool[N << 1];
     22 TrieNode* top = pool;
     23 
     24 TrieNode* newnode() {
     25     top->id = 0;
     26     top->ch[0] = top->ch[1] = NULL;
     27     return top++;
     28 }
     29 
     30 typedef class Trie {
     31     public:
     32         TrieNode* rt;
     33     
     34         Trie():rt(newnode()) {    }
     35 
     36         int insert(char* str, int id) {
     37             TrieNode* p = rt;
     38             for (int i = 0, c; str[i]; i++) {
     39                 c = str[i] - '0';
     40                 if (!p->ch[c])
     41                     p->ch[c] = newnode();
     42                 p = p->ch[c];
     43             }
     44             if (!p->id)
     45                 p->id = id;
     46             else if ((!p->vs.size() || p->vs[p->vs.size() - 1] != id - 1) && p->id != id - 1) 
     47                 p->vs.push_back(id);
     48             return p->id;
     49         }
     50 }Trie;
     51 
     52 int n, n2;
     53 char buf1[N], buf2[N];
     54 vector<int> g[N * 12];
     55 // 1 ~ 2 * n2 : Is the node seclected?
     56 // 2 * n2 + 1 ~ 4 * n2: Aren't nodes above seclected?
     57 // 4 * n2 + 1 ~ 6 * n2: Aren't nodes below seclected?
     58 Trie tr;
     59 
     60 inline void init() {
     61     scanf("%d", &n);
     62     n2 = n << 1;
     63     for (int i = 1, len, p1, p2; i <= n; i++) {
     64         scanf("%s", buf1);
     65         len = strlen(buf1);
     66         memcpy(buf2, buf1, len + 1);
     67         for (int j = 0; j < len; j++)
     68             if (buf1[j] == '?')
     69                 buf1[j] = '0';
     70         for (int j = 0; j < len; j++)
     71             if (buf2[j] == '?')
     72                 buf2[j] = '1';
     73         p1 = tr.insert(buf1, (i << 1) - 1);
     74         p2 = tr.insert(buf2, i << 1);
     75         if (p1 == p2) {
     76             g[(i << 1) - 1 + n2].push_back((i << 1) - 1);
     77         } else {
     78             p1 = ((i << 1) - 1), p2 = (i << 1);
     79             g[p1].push_back(p2 + n2);
     80             g[p2 + n2].push_back(p1);
     81             g[p2].push_back(p1 + n2);
     82             g[p1 + n2].push_back(p2); 
     83         }
     84     }
     85 }
     86 
     87 #define virt(_x) (_x + n2)
     88 #define upre(_x) (_x + n2 * 2)
     89 #define upvi(_x) (_x + n2 * 3)
     90 #define dore(_x) (_x + n2 * 4)
     91 #define dovi(_x) (_x + n2 * 5)
     92 
     93 void dfs(TrieNode* p, int last) {
     94     if (!p)    return;
     95     if (p->vs.size()) {
     96         vector<int> &ve = p->vs;
     97         for (int i = 0; i < (signed) ve.size(); i++) {
     98             TrieNode* q = newnode();
     99             q->id = ve[i];
    100             q->ch[0] = p->ch[0], q->ch[1] = p->ch[1];
    101             p->ch[1] = NULL, p->ch[0] = q;
    102         }
    103         ve.clear();
    104     }
    105     int id = p->id;
    106     if (id) {
    107         g[id].push_back(upvi(id));
    108         g[id].push_back(dovi(id));
    109         g[upre(id)].push_back(virt(id));
    110         g[dore(id)].push_back(virt(id));
    111         if (last) {
    112             g[id].push_back(upre(last));
    113             g[upvi(last)].push_back(virt(id));
    114             g[last].push_back(dore(id));
    115             g[dovi(id)].push_back(virt(last));
    116 
    117             g[upre(id)].push_back(upre(last));
    118             g[upvi(last)].push_back(upvi(id));
    119             g[dore(last)].push_back(dore(id));
    120             g[dovi(id)].push_back(dovi(last));
    121         }
    122     }
    123     int nid = ((id) ? (id) : (last));
    124     dfs(p->ch[0], nid);
    125     dfs(p->ch[1], nid);
    126 }
    127 
    128 int dfs_clock = 0;
    129 stack<int> st;
    130 boolean vis[N * 12], ins[N * 12];
    131 int dfn[N * 12], low[N * 12];
    132 void tarjan(int p) {
    133     vis[p] = true, ins[p] = true;
    134     dfn[p] = low[p] = ++dfs_clock;
    135     st.push(p);
    136     for (int i = 0; i < (signed) g[p].size(); i++) {
    137         int e = g[p][i];
    138         if (!vis[e]) {
    139             tarjan(e);
    140             low[p] = min(low[p], low[e]);
    141         } else if (ins[e])
    142             low[p] = min(low[p], dfn[e]);
    143     }
    144 
    145     if (dfn[p] == low[p]) {
    146         int cur;
    147         do {
    148             cur = st.top();
    149             st.pop();
    150             low[cur] = low[p];
    151             ins[cur] = false;
    152         } while (cur != p);
    153     }
    154 }
    155 
    156 void putans(const char* str) {
    157     puts(str);
    158     exit(0);
    159 }
    160 
    161 inline void solve() {
    162     dfs(tr.rt, 0);
    163     for (int i = 1; i <= n2 * 6; i++)
    164         if (!vis[i])
    165             tarjan(i);
    166     for (int i = 1; i <= n2; i++) {
    167         if (low[i] == low[virt(i)])
    168             putans("NO");
    169         if (low[upre(i)] == low[upvi(i)])
    170             putans("NO");
    171         if (low[dore(i)] == low[dovi(i)])
    172             putans("NO");
    173     }
    174     putans("YES");
    175 }
    176 
    177 int main() {
    178     init();
    179     solve();
    180     return 0;
    181 }
  • 相关阅读:
    数据分析之可反复与独立样本的T-Test分析
    朗朗上口的两幅对联
    mysql编码、数据表编码查看和改动总结
    2014-04-19编程之美初赛题目及答案解析
    测试集群模式安装实施Hadoop
    笔记:常用排序算法
    笔记:常用排序算法
    安装Redis并测试
    常见架构风格举例总结
    转载:PostgreSQL SQL的性能提升
  • 原文地址:https://www.cnblogs.com/yyf0309/p/9490548.html
Copyright © 2020-2023  润新知