Codeforces Round #556 (Div. 2) - D. Three Religions(动态规划)
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(动态规划)的更多相关文章
- Codeforces Round #556 (Div. 2) D. Three Religions 题解 动态规划
题目链接:http://codeforces.com/contest/1150/problem/D 题目大意: 你有一个参考串 s 和三个装载字符串的容器 vec[0..2] ,然后还有 q 次操作, ...
- Codeforces Round #556 (Div. 2) - C. Prefix Sum Primes(思维)
Problem Codeforces Round #556 (Div. 2) - D. Three Religions Time Limit: 1000 mSec Problem Descripti ...
- Codeforces Round #556 (Div. 1)
Codeforces Round #556 (Div. 1) A. Prefix Sum Primes 给你一堆1,2,你可以任意排序,要求你输出的数列的前缀和中质数个数最大. 发现只有\(2\)是偶 ...
- Codeforces Round #556 (Div. 2)
比赛链接 A 贪心 #include <cstdlib> #include <cstdio> #include <algorithm> #include <c ...
- Codeforces Round #556 (Div. 2)-ABC(这次的题前三题真心水)
A. Stock Arbitraging 直接上代码: #include<cstdio> #include<cstring> #include<iostream> ...
- Codeforces Round #382 (Div. 2)C. Tennis Championship 动态规划
C. Tennis Championship 题目链接 http://codeforces.com/contest/735/problem/C 题面 Famous Brazil city Rio de ...
- Codeforces Round #369 (Div. 2) C. Coloring Trees 动态规划
C. Coloring Trees 题目连接: http://www.codeforces.com/contest/711/problem/C Description ZS the Coder and ...
- Codeforces Round #349 (Div. 1) A. Reberland Linguistics 动态规划
A. Reberland Linguistics 题目连接: http://www.codeforces.com/contest/666/problem/A Description First-rat ...
- Codeforces Round #556 题解
Codeforces Round #556 题解 Div.2 A Stock Arbitraging 傻逼题 Div.2 B Tiling Challenge 傻逼题 Div.1 A Prefix S ...
随机推荐
- 用Redis解决互联网项目的数据读取难点
Redis在很多方面与其他数据库解决方案不同:它使用内存提供主存储支持,而仅使用硬盘做持久性的存储:它的数据模型非常独特,用的是单线程.另一个大区别在于,你可以在开发环境中使用Redis的功能,但却不 ...
- VS优化编译配置
在使用VS2010编译C++程序的时候,每次修改工程中的某一个文件,点击“生成-仅用于项目-仅生成**”时,往往都是整个工程都需要重新编译一遍.由于这个工程代码量太大,每次编译完成都需要将近10分钟左 ...
- SQL 零碎点
1,插入数据后,返回主键ID值: INSERT INTO tablename (name) VALUES (@name);SELECT @@Identity; 使用 SELECT @@Identity ...
- spring.net 继承
. <object id="parent" type="Bll.Parent, HRABLL" > <property name=" ...
- Java Persistence with MyBatis 3(中文版) 第五章 与Spring集成
MyBatis-Spring是MyBatis框架的子模块,用来提供与当前流行的依赖注入框架Spring的无缝集成. Spring框架是一个基于依赖注入(Dependency Injection)和面向 ...
- xStream完美转换XML、JSON(转)
xStream框架 xStream可以轻易的将Java对象和xml文档相互转换,而且可以修改某个特定的属性和节点名称,而且也支持json的转换: 前面有介绍过json-lib这个框架,在线博文:htt ...
- JavaScript面向对象编程小游戏---贪吃蛇
1 面向对象编程思想在程序项目中有着非常明显的优势: 1- 1 代码可读性高.由于继承的存在,即使改变需求,那么维护也只是在局部模块 1- 2 维护非常方便并且成本较低. 2 这个demo是采用了 ...
- 编写高质量代码改善C#程序的157个建议——建议148:不重复代码
建议148:不重复代码 如果发现重复的代码,则意味着我们需要整顿一下,在继续前进. 重复的代码让我们的软件行为不一致.举例来说,如果存在两处相同的加密代码.结果在某一天,我们发现加密代码有个小Bug, ...
- 理解Javascript的Prototype
在Javascript中创建对象主要分为三种方式 1. var catA = {name: "Fluffy", color: "White", age: 0}; ...
- Android 热修复技术中的CLASS_ISPREVERIFIED问题
一.前言 上一篇博客中,我们通过介绍dex分包原理引出了Android的热补丁技术,而现在我们将解决两个问题. 1. 怎么将修复后的Bug类打包成dex 2. 怎么将外部的dex插入到ClassLoa ...