原文链接https://www.cnblogs.com/zhouzhendong/p/AGC026E.html

题目传送门 - AGC026E

题意

  给定一个长度为 $2n$ 的字符串,包含 $n$ 个 $'a'$ 和 $n$ 个 $'b'$ 。

  现在,让你按照原顺序取出一些字符,按照原顺序组成新的字符串,输出所有满足条件的字符串中字典序最大的?(字典序: $'b'>'a'>'\ '$)

  条件限制:当且仅当取了原序列的第 $i$ 个 $'a'$ 时,原序列的第 $i$ 个 $'b'$ 也被取了。

  $n\leq 3000$

题解

  比赛结束前 30 分钟想到正解。

  赛后 20 多分钟 AC 了。

  第一次开黑好爽啊。

  早知道就把做 D 题的时间搬到后面来了(写了一半 xza AC 了)。这样的话就可以打到 30 多名了。

  扯淡完毕,言归正传。

  我们首先考虑一个显然的东西:

  开头要有尽量多个 $b$ 。

  然后,我们再考虑个东西。

  当你已经选择了一些 $b$ 之后,不可避免的来了个 $a$ ,你如果选了这个 $a$ ,答案最大为什么?

  bbbbba...a...a....a....a.....

  假设之前选择的 b 的对应 a 如上所述,那么为了保证字典序最大,我们得取光所有在前 4 个省略号区间里面的 b 。

  而这些 b 所对应的 a 必然在上述最后一个 a 后面。因为这些新选的 a 所对应的 b 在之前那些 a 所对应的 b 的后面。

  在选择完这些新的 b 和 a 之后,样子大概变成了这样:

  bbbbbabbabbbabbbabbaba......a....a...a

  于是你可以发现我们由要在新生的省略号区域取 $b$ 来保证最优。

  那么不断这样做,什么时候结束呢?

  当这一串  a 的个数 = b 的个数 时。

  我们称选择这些 a 和 b 并结束,为一次“区间贪心变换”。注意这个定义到后面我会讲的模糊些,与这里写的意义可能会有一点偏差。

  那么我们要在一个新的串中求解原来的求最大字典序串的问题。

  这个新的串就是原串除掉你当前选择的这一段之后留下的后缀串。

  我们在求后缀串答案的时候,又会去求后缀串的后缀串的答案。

  于是我们可以观察一下哪些后缀串会被求解。

  事实上,如果一个后缀串包含的 $a$ 的个数与包含的 $b$ 的个数相同,那么就会被求解。

  我们再回到原问题。

  我们称第 $i$ 个后缀的左端点为第 $i$ 个停止点,(最后一个停止点在 $n+1$ 位置,代表空后缀)

  那么,任何一个后缀进行一次“区间贪心变换”之后,一定会到达下一个停止点。

  这个东西的证明,留给你了。

  于是,一个后缀的求解结果就是他的任何“区间贪心变换”结果与下一个停止点开始的后缀的求解结果拼接的最大值。

  为什么说“任何“区间贪心变换””?显然,有可能有多种非常优秀的区间贪心变换。即多种前缀 b 个数最多的区间贪心变换。

  这个东西用个队列就可以了。

  于是这个问题就转化成了一个分阶段贪心的题目,可以理解成贪心 + DP 。

  注意一下,当前后缀的答案还可以直接从下一个后缀继承。

  

  当然,还有一种特殊情况!

  最优区间贪心变换的前缀 b 个数可能为 $0$ 。我们可以发现,这种情况下,每一个 b 对应的 a 都在它前面。

  我们可以考虑贪心的取形如 $ab\cdots ab$ 串,并每多取一个 $ab$ 就和下一个后缀一起更新一下当前的 dp 值。

  然后就完了。时间复杂度 $O(n^2)$ 。(可以写一些简单的优化来加速,但是这样的复杂度已经足够通过了)

  只可惜刚开始写的时候没想到后面这种特殊情况。

  我可能是思考的不够透彻,导致我写出来的可能有点凌乱。

  但是我把代码写出来 AC 了。

  欢迎提问。

  一篇深入理解的简洁明了的题解我就先欠着吧……

代码

#include <bits/stdc++.h>
using namespace std;
const int N=6005;
int n,p[N],pp[N],t[N];
int q[N],head,tail;
string res[N],now;
char s[N];
vector <int> a,b;
int main(){
scanf("%d",&n);
n<<=1;
scanf("%s",s+1);
a.clear(),b.clear();
for (int i=1;i<=n;i++)
if (s[i]=='a')
a.push_back(i);
else
b.push_back(i);
for (int i=1;i<=n/2;i++)
p[b[i-1]]=a[i-1],pp[a[i-1]]=b[i-1];
for (int i=1;i<=n+1;i++)
res[i]="";
int tot=0;
int nxt=n+1;
for (int i=n;i>=1;i--){
if (s[i]=='a')
tot++;
else
tot--;
if (tot)
continue;
memset(t,0,sizeof t);
head=1,tail=0;
res[i]=res[nxt];
for (int j=i;j<nxt;j++){
if (s[j]=='a'){
if (t[j]){
now="";
for (int k=i;k<nxt;k++)
if (s[k]=='b'){
if (t[k]||k>j)
now+="b";
}
else if (t[k]||k>p[q[tail]])
now+="a";
res[i]=max(res[i],now+res[nxt]);
head++;
t[j]=t[pp[j]]=0;
}
continue;
}
if (p[j]<j)
continue;
q[++tail]=j;
t[j]=t[p[j]]=1;
}
memset(t,0,sizeof t);
if (tail==0){
for (int j=i;j<nxt;j++){
if (s[j]=='b')
continue;
t[j]=t[pp[j]]=1;
now="";
for (int k=i;k<=pp[j];k++)
if (t[k])
now+=s[k];
res[i]=max(res[i],now+res[nxt]);
j=pp[j];
}
}
nxt=i;
}
cout << res[1];
return 0;
}

  

AtCoder Grand Contest 026 (AGC026) E - Synchronized Subsequence 贪心 动态规划的更多相关文章

  1. Atcoder Grand Contest 026 (AGC026) F - Manju Game 博弈,动态规划

    原文链接www.cnblogs.com/zhouzhendong/AGC026F.html 前言 太久没有发博客了,前来水一发. 题解 不妨设先手是 A,后手是 B.定义 \(i\) 为奇数时,\(a ...

  2. AtCoder Grand Contest 026 D - Histogram Coloring

    一列中有两个连续的元素,那么下一列只能选择选择正好相反的填色方案(因为连续的地方填色方案已经确定,其他地方也就确定了) 我们现将高度进行离散化到Has数组中,然后定义dp数组 dp[i][j] 表示前 ...

  3. AtCoder Grand Contest #026 C - String Coloring

    Time Limit: 3 sec / Memory Limit: 1024 MB Score : 600600 points Problem Statement You are given a st ...

  4. AtCoder Grand Contest #026 B - rng_10s

    Time Limit: 2 sec / Memory Limit: 1024 MB Score : 600600 points Problem Statement Ringo Mart, a conv ...

  5. AtCoder Grand Contest #026 A - Colorful Slimes 2

    Time Limit: 2 sec / Memory Limit: 1024 MB Score : 200200 points Problem Statement Takahashi lives in ...

  6. AtCoder Grand Contest 030 (AGC030) F - Permutation and Minimum 动态规划

    原文链接www.cnblogs.com/zhouzhendong/p/AGC030F.html 草率题解 对于每两个相邻位置,把他们拿出来. 如果这两个相邻位置都有确定的值,那么不管他. 然后把所有的 ...

  7. AtCoder Grand Contest 044 A Pay to Win 贪心

    LINK:Pay to Win 自闭了 比赛的时候推出来正解了 以为复杂度不对 写完扔了 没拿map存状态就扔了23333... 一个T点:在更新map的时候 >不要写成>= 不然会徒劳的 ...

  8. AtCoder Grand Contest 031 简要题解

    AtCoder Grand Contest 031 Atcoder A - Colorful Subsequence description 求\(s\)中本质不同子序列的个数模\(10^9+7\). ...

  9. AtCoder Grand Contest 012

    AtCoder Grand Contest 012 A - AtCoder Group Contest 翻译 有\(3n\)个人,每一个人有一个强大值(看我的假翻译),每三个人可以分成一组,一组的强大 ...

随机推荐

  1. 5分钟搞定Nginx安装

      1. 安装gcc(centos 7之后一般已自带,可以在第6步失败后再安装) yum install gcc gcc-c++   2. 安装pcre yum install -y pcre pcr ...

  2. 24)django-信号

    目录 1)django信号简介 2)django内置信号 3)django自定义信号 一:django信号简介 Django中提供了“信号调度”,用于在框架执行操作时解耦. 通俗来讲,就是一些动作发生 ...

  3. 如何用Axure快速制作APP交互原型

    对于产品经理来说,熟练使用一些常用软件是一项十分必要的技能.其中,作为一个专业的快速原型设计工具,Axure RP无疑在产品人心中拥有一个难以撼动的地位.但就要PS一样,虽然足够专业,但同样也会存在使 ...

  4. 洛谷P4827 [国家集训队] Crash 的文明世界 [斯特林数,组合数,DP]

    传送门 思路 又见到这个\(k\)次方啦!按照套路,我们将它搞成斯特林数: \[ ans_x=\sum_{i=0}^k i!S(k,i)\sum_y {dis(x,y) \choose i} \] 前 ...

  5. HTML_1

    HTML 指的是超文本标记语言: HyperText Markup LanguageHTML 不是一种编程语言,而是一种标记语言标记语言是一套标记标签 (markup tag)HTML 使用标记标签来 ...

  6. centos6.5磁盘扩容

    3台虚拟机都是20G磁盘,用着用着发现不够了,先扩容了一台,各种百度...各种坑,每个人的情况不一样,发现不一样的地方最后立即百度查看.一台扩容成功后,打算再扩容一台,目的是留一个记录.(我是用xsh ...

  7. 信息摘要算法之四:SHA512算法分析与实现

    前面一篇中我们分析了SHA256的原理,并且实现了该算法,在这一篇中我们将进一步分析SHA512并实现之. 1.SHA简述 尽管在前面的篇章中我们介绍过SHA算法,但出于阐述的完整性我依然要简单的说明 ...

  8. 机器学习之高斯混合模型及EM算法

    第一部分: 这篇讨论使用期望最大化算法(Expectation-Maximization)来进行密度估计(density estimation). 与k-means一样,给定的训练样本是,我们将隐含类 ...

  9. Oracle管理文件OMF (oracle managed files)

    简化dba的管理操作 1:启用 omf 23:16:04 SYS@orcl> show parameter DB_CREATE_FILE_DEST NAME TYPE VALUE ------- ...

  10. 【Myeclipse】用Myeclipse10.5搭建C/C++开发环境

    一.添加CDT到Myeclipse10.5 我的Myeclipse版本是10.5,刚开始用Myeclipse configuration center添加安装,不管是用远程URL还是用本地Archiv ...