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 ...
随机推荐
- jdk8中的StreamAPI
1.实体类 package com.zy.model; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.D ...
- cacti-不出图形,cacti.log中出“ERROR: SQL Assoc Failed!
[root@CactiEZ log]# tail cacti.log 2016年04月06日 14:53:16 PM - CMDPHP: Poller[0] ERROR: SQL Cell Faile ...
- 采用AutoIt实现文件上传
在非常规的上传界面中,AutoIt可以操作Windows资源管理器实现上传路径的输入. AutoIt中编辑以下脚本,需通过“AutoIt Windows Info”定位资源管理器路径输入位置信息及打开 ...
- Monkey&Monkey Runner使用
adb shell monkey -p com.ajb.sp -s 500 --ignore-crashes --ignore-timeouts --monitor-native-crashes -v ...
- linux fuser的使用
当进行共享存储的时候,umount可能无法用于卸载某个设备,说是被某个进程所占用,但是又无法找到该进程.这个时候使用fuser -km /data命令杀死所有在使用这个存储设备的进程然后再umount ...
- 三个参数,对mysql存储限制的影响
1.max_allowed_packet 这个参数会影响单此插入或读取的包的大小,一般和blob字段共用,但要注意一点是这个参数好像是分服务端与客户端的,如果想输出大字段的内容,则在用客户端链接服务 ...
- dedecms开启报错调试
位置:/include/common.inc.php //error_reporting(E_ALL); error_reporting(E_ALL || ~E_NOTICE); 替换成 error_ ...
- HBase表的memstore与集群memstore
一直有一个问题,今天调查了一下源码算是明白了. ===问题=== 通过java api(如下代码所示)在创建表的时候,可以通过setMemStoreFlushSize函数来指定memstore的大小, ...
- Spring MVC 配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...
- Android Touch 事件总结
---恢复内容开始--- 1.Touch事件传递机制 过程有点儿类似于栈, ViewGroup的子类有都继承它的以下3个方法: public boolean dispatchTouchEvent(Mo ...