Problem  Codeforces Round #556 (Div. 2) - D. Three Religions

Time Limit: 3000 mSec

Problem Description

Input

Output

Sample Input

6 8
abdabc
+ 1 a
+ 1 d
+ 2 b
+ 2 c
+ 3 a
+ 3 b
+ 1 c
- 2

Sample Output

YES
YES
YES
YES
YES
YES
NO
YES

题解:动态规划,意识到这个题是动态规划之后难点在于要优化什么东西,本题是让判断原串能否划分成题中不断更新的三个字符串,通常情况下dp数组不仅仅记录true/false这种信息,因为这种信息往往可以在不改变复杂度的情况下通过记录更具体的信息来直接导出,而这些更具体的信息会给状态的转移带来便利,本题就是这样的情况。

  意识到本题的dp属于分段决策同样很重要,对于当前的三个字符串,判断是否合法的方式是逐个加入字符,逐个加入的过程就是天然的阶段,而每个阶段需要做出的决策是加入哪一个字符串的字符,在这个过程中维护的信息就是把第一个串的前 a 个字符,第二个串的前 b 个字符,第三个串的前 c 个字符放进去所需要原串的最小长度。

  有了这样的状态定义转移方程自然很简单,比如考虑dp[a][b][c],并且是从dp[a-1][b][c]转移过来的,那么dp[a][b][c]就是在dp[a-1][b][c]位置之后第一次出现第一个串第a个字符的位置,为了能够O(1)转移,预处理出对于原串的每个位置i,对每个小写英文字母x,i及i以后第一次出现x的位置,这很容易在O(26 * n)的复杂度内解决。这样每次状态转移只需要常数时间,正常情况下总的复杂度是O(q * 250^3),这肯定会T,但是考虑到每次新加入一个字符需要重新计算的dp值只有250^2个,因此复杂度实际为O(q * 250^2),可以接受。

 #include <bits/stdc++.h>

 using namespace std;

 #define REP(i, n) for (int i = 1; i <= (n); i++)
#define sqr(x) ((x) * (x)) const int maxn = + ;
const int maxm = + ;
const int maxs = ; typedef long long LL;
typedef pair<int, int> pii;
typedef pair<double, double> pdd; const LL unit = 1LL;
const int INF = 0x3f3f3f3f;
const double eps = 1e-;
const double inf = 1e15;
const double pi = acos(-1.0);
const int SIZE = + ;
const LL MOD = ; int n, q;
int type;
int Next[maxn][];
int dp[maxs][maxs][maxs];
string str, opt, word;
string ss[]; void cal(int a, int b, int c)
{
int &ans = dp[a][b][c];
ans = n;
if (a)
ans = min(ans, Next[dp[a - ][b][c] + ][ss[][a - ] - 'a']);
if (b)
ans = min(ans, Next[dp[a][b - ][c] + ][ss[][b - ] - 'a']);
if (c)
ans = min(ans, Next[dp[a][b][c - ] + ][ss[][c - ] - 'a']);
} void premanagement()
{
for (int i = ; i < ; i++)
{
Next[n][i] = Next[n + ][i] = n;
}
for (int i = n - ; i >= ; i--)
{
int tmp = str[i] - 'a';
for (int j = ; j < ; j++)
{
if (j != tmp)
Next[i][j] = Next[i + ][j];
else
Next[i][j] = i;
}
}
} int main()
{
ios::sync_with_stdio(false);
cin.tie();
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout); cin >> n >> q;
cin >> str;
premanagement();
dp[][][] = -;
for (int i = ; i < q; i++)
{
cin >> opt >> type;
type--;
if (opt[] == '+')
{
cin >> word;
ss[type] += word[];
int max0 = ss[].size(), max1 = ss[].size(), max2 = ss[].size();
int min0 = (type == ? max0 : );
int min1 = (type == ? max1 : );
int min2 = (type == ? max2 : );
for (int a = min0; a <= max0; a++)
{
for (int b = min1; b <= max1; b++)
{
for (int c = min2; c <= max2; c++)
{
cal(a, b, c);
}
}
}
}
else
{
ss[type].pop_back();
} if (dp[ss[].size()][ss[].size()][ss[].size()] < n)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
return ;
}

Codeforces Round #556 (Div. 2) - D. Three Religions(动态规划)的更多相关文章

  1. Codeforces Round #556 (Div. 2) D. Three Religions 题解 动态规划

    题目链接:http://codeforces.com/contest/1150/problem/D 题目大意: 你有一个参考串 s 和三个装载字符串的容器 vec[0..2] ,然后还有 q 次操作, ...

  2. Codeforces Round #556 (Div. 2) - C. Prefix Sum Primes(思维)

    Problem  Codeforces Round #556 (Div. 2) - D. Three Religions Time Limit: 1000 mSec Problem Descripti ...

  3. Codeforces Round #556 (Div. 1)

    Codeforces Round #556 (Div. 1) A. Prefix Sum Primes 给你一堆1,2,你可以任意排序,要求你输出的数列的前缀和中质数个数最大. 发现只有\(2\)是偶 ...

  4. Codeforces Round #556 (Div. 2)

    比赛链接 A 贪心 #include <cstdlib> #include <cstdio> #include <algorithm> #include <c ...

  5. Codeforces Round #556 (Div. 2)-ABC(这次的题前三题真心水)

    A. Stock Arbitraging 直接上代码: #include<cstdio> #include<cstring> #include<iostream> ...

  6. Codeforces Round #382 (Div. 2)C. Tennis Championship 动态规划

    C. Tennis Championship 题目链接 http://codeforces.com/contest/735/problem/C 题面 Famous Brazil city Rio de ...

  7. Codeforces Round #369 (Div. 2) C. Coloring Trees 动态规划

    C. Coloring Trees 题目连接: http://www.codeforces.com/contest/711/problem/C Description ZS the Coder and ...

  8. Codeforces Round #349 (Div. 1) A. Reberland Linguistics 动态规划

    A. Reberland Linguistics 题目连接: http://www.codeforces.com/contest/666/problem/A Description First-rat ...

  9. Codeforces Round #556 题解

    Codeforces Round #556 题解 Div.2 A Stock Arbitraging 傻逼题 Div.2 B Tiling Challenge 傻逼题 Div.1 A Prefix S ...

随机推荐

  1. 二、SQL的生命周期

    MySQL的sql语句由客户端发出,经过连接和权限验证后,最终达到服务器端,由服务器分配thread线程处理,之后就是要介绍的具体服务器端的thread线程是怎么处理每条sql语句的.[ 了解thre ...

  2. oracle 创建一个用户,只能访问指定的对象

    1>创建一个ORACLE 的用户 create user username identified by pws; 2>给用户授权  grant connect,resource to us ...

  3. PythonQt第一例

    pythonQt第一例源码如下,主要介绍了简单的使用方式,需要注意的是应用程序的debug版本和release版本必须使用同类型的PythonQt库不可交叉使用. 源码地址:http://files. ...

  4. Python之FTP传输-乾颐堂

    访问FTP,无非两件事情:upload和download,最近在项目中需要从ftp下载大量文件,然后我就试着去实验自己的ftp操作类,如下(PS:此段有问题,别复制使用,可以参考去试验自己的ftp类! ...

  5. docker镜像存出与载入

    尝试从官网上下载ubuntu镜像,太慢下载不下来. 使用daocloud加速器进行加速之后,由于公司网络不好,仍然下载不下来. 没办法,只能从别的环境上搞一个已经存在的ubuntu镜像,折腾到自己的虚 ...

  6. 没有Reduce的MapReduce(一)

    尝试了一个没有Reduce的MapReduce. [应用场景]: 从Hbase的A表中进行数据抽样,直接输出到B表中. 这种场景下,相当于只进行了一个数据检索,本来是用Hive就可以实现,但是考虑到业 ...

  7. 实践作业3:白盒测试----学习Junit框架DAY10.

    JUnit - 测试框架 首先应该了解什么是 Junit 测试框架? JUnit 是一个回归测试框架,被开发者用于实施对应用程序的单元测试,加快程序编制速度,同时提高编码的质量.JUnit 测试框架能 ...

  8. Smarty配置与实例化

    在smarty文件夹下建立一个test文件夹,test下建立如下: 编辑test.php如下: <?php require('../smarty/Smarty.class.php'); $sma ...

  9. ceph中pool的管理

    1.创建pool 创建ceph pool的命令如下,它的参数包括pool名字.PG和PGP的数量. 若少于5个OSD, 设置pg_num为128. 5~10个OSD,设置pg_num为512. 10~ ...

  10. Linq学习<五> 运用linq查询Xml

    这节将学习如何用 linq查询xml 一.我们先看看在xml中我们怎么操作 public void xmlWayToQueryXmlFile() { XmlDocument xmldoc = new ...