题目链接


\(Description\)

给定一个长为\(n\)的足迹序列(只包含\(L,R\)两种字符),你需要\(LRLRLR...\)这样交替在\(L\)和\(R\)上走(第一步可以选择\(L\)也可以选\(R\))。当你在\(L\)时,下一步可以走到任意一个没走过的\(R\);在\(R\)时,下一步可以走到任意一个没走过的\(L\)。求走完这个\(L,R\)序列最少需要往回走几次,并输出方案(往回走是指从位置\(i\)走到位置\(j\),\(j\lt i\))。保证存在一组可行方案。

\(n\leq10^5\)。

\(Solution\)

首先\(L,R\)数量差大于\(1\)无解。

如果我们需要往回走\(k\)次,那么我们可以将序列分成\(k+1\)个分别合法的子序列。

反过来,如果我们能将序列分成\(k\)个合法的子序列,小于往回走的次数是不是一定小于\(k\)?

考虑能否证明。我们将序列分成\(LL,RR,LR,RL\)四种合法的子序列(第一个字符表示序列开始是什么,第二个字符表示序列末尾是什么,因为只需要关心首尾字符),假设四种子序列分别有\(a,b,c,d\)个。首先有\(|a-b|\leq1\)。

然后我们可以用不超过\(a+b-1\)步将所有\(LL,RR\)合并成一个序列,这个序列可能是四种中的任意一种。

还可以用不超过\(c-1\)步将所有\(LR\)合并成一个\(LR\)。对\(RL\)同理。这样我们就得到了一个\(LR\)和一个\(RL\)子序列。

如果把其中一个子序列的最后一个字符给另一个,就可以变成一个\(LL\)和一个\(RR\),且不会增加次数。

那么不论刚开始\(LL,RR\)合并出的子序列是哪种,都可以用不超过两步拼接上剩下的两个子序列。

这样最多使用\(a+b-1+c-1+d-1+2=k-1\)步。这样就证明了,如果我们能能将序列划分成\(k\)个合法子序列,一定可以构造方案使得最多往回走\(k-1\)次。(可是我还是觉得有点迷...)

现在的问题是怎么讲序列划分成尽量少的合法子序列。

我们发现可以跑最小路径覆盖(每个\(L/R\)向它后面所有\(R/L\)连边,\(n-最大匹配数\)就是答案)(图在官方题解里有)。

但还可以发现这个匹配实际上可以直接贪心,每个字符选它能匹配的点中最靠前的匹配即可。因为一定可以调整最大匹配使得满足这种贪心。

那么复杂度就是\(O(n)\)的了。

具体做的时候,可以拿个栈模拟一下拼接...(菜到不会写.jpg)


//46ms	1900KB
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define AE(u,v) nxt[u]=v, pre[v]=u
typedef long long LL;
const int N=1e5+5; int top,pre[N],nxt[N];
std::queue<int> q[2];
char s[N];
struct Node
{
int l,r;
}sk[N]; bool Maintain()
{
if(top<=1) return 0;
Node a=sk[top],b=sk[top-1];
if(s[a.r]!=s[b.l])
{
AE(a.r,b.l), sk[--top]=(Node){a.l,b.r};
return 1;
}
if(s[a.l]!=s[b.r])
{
AE(b.r,a.l), sk[--top]=(Node){b.l,a.r};
return 1;
}
if(s[a.l]!=s[b.l])//LR RL
{
if(a.r>b.r) std::swap(a,b);
int p=pre[b.r];
AE(a.r,b.r), AE(b.r,b.l), nxt[p]=0, sk[--top]=(Node){a.l,p};
return 1;
}
return 0;
} int main()
{
scanf("%s",s+1);
const int n=strlen(s+1);
for(int i=1,c; i<=n; q[c^1].push(i++))
if(!q[c=s[i]=='L'].empty()) AE(q[c].front(),i), q[c].pop();
int ans=0;
for(int i=1; i<=n; ++i)
if(!pre[i])
{
++ans;
int p=i; while(nxt[p]) p=nxt[p];
sk[++top]=(Node){i,p};
while(Maintain());
}
printf("%d\n",ans-1);
for(int x=sk[1].l; x; x=nxt[x]) printf("%d ",x); return 0;
}

Codeforces.578E.Walking(构造)的更多相关文章

  1. CodeForces 578E Walking!

    题意 略. 题解 好毒瘤啊,我最多就口胡第一问的样子吧. 第一问很显然(跟凤凰县探险队员一样显然),就是每次贪心选长度最大的满足条件的子序列,选不到就折返回来.所以折返的次数很明显就是选出子序列的个数 ...

  2. codeforces 1041 e 构造

    Codeforces 1041 E 构造题. 给出一种操作,对于一棵树,去掉它的一条边.那么这颗树被分成两个部分,两个部分的分别的最大值就是这次操作的答案. 现在给出一棵树所有操作的结果,问能不能构造 ...

  3. Codeforces - 474D - Flowers - 构造 - 简单dp

    https://codeforces.com/problemset/problem/474/D 这道题挺好的,思路是这样. 我们要找一个01串,其中0的段要被划分为若干个连续k的0. 我们设想一个长度 ...

  4. Codeforces Global Round 8 B. Codeforces Subsequences(构造)

    题目链接:https://codeforces.com/contest/1368/problem/B 题意 构造最短的至少含有 $k$ 个 $codeforces$ 子序列的字符串. 题解 如下表: ...

  5. Codeforces 410C.Team[构造]

    C. Team time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  6. Codeforces 716C[数论][构造]

    /* CF傻逼构造题 某人要经过n回合游戏,初始分值是2,等级为1. 每次有两种操作 1.无条件,分值加上自己的等级数. 2.当目前的数字是完全平方数并且该数字开方以后是等级数加1的整数倍,那么可以将 ...

  7. Codeforces 1154D - Walking Robot - [贪心]

    题目链接:https://codeforces.com/contest/1154/problem/D 题解: 贪心思路,没有太阳的时候,优先用可充电电池走,万不得已才用普通电池走.有太阳的时候,如果可 ...

  8. Tea Party CodeForces - 808C (构造+贪心)

    Polycarp invited all his friends to the tea party to celebrate the holiday. He has ncups, one for ea ...

  9. New Roads CodeForces - 746G (树,构造)

    大意:构造n结点树, 高度$i$的结点有$a_i$个, 且叶子有k个. 先确定主链, 然后贪心放其余节点. #include <iostream> #include <algorit ...

随机推荐

  1. dbcp连接池出现的问题java.lang.AbstractMethodError: com.mysql.jdbc.Connection.isValid(I)Z

    解决方案:mysql-connector 版本为 5.0.4 ,那么对应的 dbcp 和 pool 版本应该为 1.4 和 1.6 .    5.0.4 不应该使用 2.0 及以上版本的 dbcp 和 ...

  2. uva11426 欧拉函数应用,kuangbin的筛法模板

    /* 给定n,对于所有的对(i,j),i<j,求出sum{gcd(i,j)} 有递推式sum[n]=sum[n-1]+f[n] 其中f[n]=gcd(1,n)+gcd(2,n)+gcd(3,n) ...

  3. API接口加密方式说明

    标签: 接口 2016年10月11日 19:41:20 13299人阅读 评论(0) 收藏 举报  分类: API(5)  版权声明:本文为博主原创文章,未经博主允许不得转载. http://blog ...

  4. python面向对象三大特性之封装

    一. 概述 定义:隐藏对象的属性和实现细节,仅对外提供公共访问方式 封装的原则:把不需要对外提供的内容都隐藏起来,提供公共的方法访问这些隐藏属性 二.封装手段 使用双下划线将属性和方法隐藏起来 cla ...

  5. 使用CSS选择器定位页面元素

    摘录:http://blog.csdn.net/defectfinder/article/details/51734690 CSS选择器也是一个非常好用的定位元素的方法,甚至比Xpath强大.在自动化 ...

  6. linux服务器上简单命令

    linux命令 1.ifconfig 查看 设置ip: 2.连接另一台linux 命令 ssh; 3.查看尾部 新追加内容 tail -f; 4.ln -s 原命令 新命令路径: 5.创建一个空文件 ...

  7. java编译通过,为什么运行却提示找不到或无法加载主类?

    java编译通过,为什么运行却提示找不到或无法加载主类? https://www.zhihu.com/question/36537093 这边提供一个关于程序中含有package关键字,使用“终端”运 ...

  8. OpenCV trackbar 避免使用全局变量

    OpenCV trackbar 避免使用全局变量 在OpenCV中使用trackbar是交互式地图像处理的一种方式,例如用于图像阈值分割,用户可以一边调整阈值一边看效果.但是很不幸,绝大多数教程上使用 ...

  9. ExceptionLess本地环境部署

    1.先去看看github上面本地流程说明 https://github.com/exceptionless/Exceptionless/wiki/Self-Hosting 比较总要的环境有 NET 4 ...

  10. 【转】Android逆向入门流程

    原文:https://www.jianshu.com/p/71fb7ccc05ff 0.写在前面 本文是笔者自学笔记,以破解某目标apk的方式进行学习,中间辅以原理性知识,方便面试需求. 参考文章的原 ...