@atcoder - [email protected] Simple Subsequence Problem

目录

  • @[email protected]
  • @[email protected]
  • @accepted [email protected]
  • @[email protected]

@[email protected]

给定由若干长度 <= N 的 01 字符串组成的集合 S。请找到长度最长的串 t(如果有多个选字典序最小的),使得存在 >= K 个 S 中的字符串,使得 t 是这些字符串的子序列。

原题题面。

@[email protected]

先看看怎么检验串 t 是否为某个串 s 的子序列:从前往后匹配,贪心地找最前面一个能够匹配上的。

注意到匹配的过程可以建图:每个种类的串 s 建点,向第一次出现的 0/1 对应的后缀连边。
每个点的连边是 O(1),因此假如把所有 <= N 的串建这个图,实际得到的图也不会很大。

于是就有一个思路:枚举 t,每次将 S 中的串对应的点在这个图上进行移动,看剩余的点是否依然 >= K 个。
看似会 TLE,然而可以修正一下:如果两个字符串走到了同一个点,下一次只移动这一个点即可。

看似还会 TLE,实际上可以过了。
因为每个长度为 p 的字符串会有 2^p 种可能性,而它继续往下匹配只会剩下 2^(N-p) 种匹配可能。因此每一个 p 都是 O(2^N) 的复杂度。
因此总复杂度为 O(N*2^N) (应该是吧,没有认真算过)。

@accepted [email protected]

#include <cstdio>

int ch[2][1<<22], id[22][1<<21], cnt;
void get() {
    id[0][0] = (cnt++), ch[0][id[0][0]] = ch[1][id[0][0]] = -1;
    for(int i=1;i<=20;i++) {
        int t = (1 << i), k = (t >> 1);
        for(int s=0;s<t;s++) {
            id[i][s] = (cnt++);
            int p = (s & k), q = (p ? 1 : 0);
            ch[q][id[i][s]] = id[i-1][s^p];
            ch[!q][id[i][s]] = ch[!q][id[i-1][s^p]];
        }
    }
}

int a[22][1<<22], siz[22], c[22][1<<22], num[22][1<<22];

int ans[22], N, K;
void dfs(int d, int s) {
    if( ans[d] == -1 ) ans[d] = s;
    for(int p=0;p<=1;p++) {
        int tot = 0;
        for(int i=0;i<siz[d];i++) {
            int to = ch[p][a[d][i]];
            if( to == -1 ) continue;
            if( num[d + 1][to] == -1 )
                num[d + 1][a[d + 1][siz[d + 1]] = to] = siz[d + 1], siz[d + 1]++;
            tot += c[d][i], c[d + 1][num[d + 1][to]] += c[d][i];
        }
        if( tot >= K ) dfs(d + 1, (s << 1) | p);
        for(int i=0;i<siz[d + 1];i++)
            num[d + 1][a[d + 1][i]] = -1, c[d + 1][i] = 0;
        siz[d + 1] = 0;
    }
}

char s[1<<21];
int main() {
    scanf("%d%d", &N, &K), get();
    for(int i=0;i<=N;i++)
        for(int j=0;j<cnt;j++)
            num[i][j] = -1;
    for(int i=0;i<=N;i++) {
        scanf("%s", s);
        int t = (1 << i);
        for(int j=0;j<t;j++) {
            if( s[j] == '1' )
                num[0][a[0][siz[0]] = id[i][j]] = siz[0], c[0][num[0][id[i][j]]]++, siz[0]++;
        }
        ans[i] = -1;
    }
    dfs(0, 0);
    for(int i=N;i>=0;i--) {
        if( ans[i] != -1 ) {
            for(int j=i-1;j>=0;j--)
                putchar(((ans[i] >> j) & 1) + '0');
            puts(""); return 0;
        }
    }
}

@[email protected]

事实证明再怎么精打细算还是有想象之外的越界危险。

还不如直接数组开大 2 倍。

原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/12211035.html

时间: 2024-10-09 23:51:26

@atcoder - [email protected] Simple Subsequence Problem的相关文章

@atcoder - [email&#160;protected] Contest with Drinks Hard

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定序列 T1, T2, ... TN,你可以从中选择一些 Ti,可以选择 0 个(即不选). 定义你选择的权值 = (满足 T[L...R] 都被选择的区间 [L, R] 的数量)-(你选择的 Ti 之和),你希望这个权值尽量大. 现在有 M 次询问,每次询问假如将 T[Pi] 修改

@atcoder - [email&#160;protected] Colorful Tree

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 题面明天起来补... @[email protected] 跟颜色有关,虽然题目中说是要"修改"实际上每一个询问之间是独立的,即修改不会有时效性. 所以不难想到可以使用树上莫队. 首先将边的颜色与边权下放至点.然后莫队时,统计出区间内每个点的点权(就是下放的边权)和 S.区间

@atcoder - [email&#160;protected] Gachapon

目录 @[email protected] @solution - [email protected] @accepted code - [email protected] @solution - [email protected] @accepted code - [email protected] @[email protected] @[email protected] 一个随机数发生器会生成 N 种数. 第 i 种数有参数 Ai,记 SA = ∑Ai,随机数发生器会有 Ai/SA 的概率

@atcoder - [email&#160;protected] RNG and XOR

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一个值域在 [0, 2^N) 的随机数生成器,给定参数 A[0...2^N-1]. 该生成器有 \(\frac{A_i}{\sum A}\) 的概率生成 i,每次生成都是独立的. 现在有一个 X,初始为 0.每次操作生成一个随机数 v 并将 X 异或 v. 对于每一个 i ∈ [0

@atcoder - [email&#160;protected] Two Trees

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定两棵树 A, B.现你需要构造一组值 (X1, X2, ..., XN)(两棵树编号相同的点对应权值相同),使得两棵树内任意子树的权值和的绝对值为 1. 无解输出 IMPOSSIBLE. 原题链接. @[email protected] 由于权值和为 1,可以推算出每个结点的奇偶性

@atcoder - [email&#160;protected] Next or Nextnext

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一个长度为 N 的序列 a,问有多少排列 p,满足对于每一个 i,都有 \(a_i = p_i\) 或 \(a_i = p_{p_i}\) 成立. 原题传送门. @[email protected] 为了更直观地理解问题,不妨建个图:连有向边 \(i -> p_i\). 对于任意序

@codeforces - [email&#160;protected] Mashmokh&#39;s Designed Problem

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一棵 n 个点的树,每个点的儿子是有序的. 现给定 m 次操作,每次操作是下列三种中的一种: (1)给定 u, v,询问 u, v 之间的距离. (2)给定 v, h,断开 v 到父亲的边,将 v 这棵子树加入到它的第 h 个祖先的最后一个儿子. (3)给定 k,询问在当前这棵树上

@hdu - [email&#160;protected] Subsequence

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定如下计算序列权值的函数: 对于一个由三元组 (cost0, cost1, color) 组成的序列 A,求通过以上函数计算出来的第 k 大的子序列的权值. Input 第一行一个整数 t,表示数据组数. 对于每组数据,第一行包含两个整数 n, k. 接下来 n 行,每行三个整数 c

@atcoder - CODE FESTIVAL 2017 Final - [email&#160;protected] Tree MST

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定 N 个点,第 i 点有一个点权 Xi,再给定一棵边带权的树,第 i 条 (Ai, Bi) 边权为 Ci. 构建一个完全图,完全图中边 (i, j) 的边权为 dist(i, j) + Xi + Xj,其中 dist(i, j) 是点 i 与点 j 在树上的距离. 求该完全图的最小