Codeforces.578E.Walking(构造)
\(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(构造)的更多相关文章
- CodeForces 578E Walking!
题意 略. 题解 好毒瘤啊,我最多就口胡第一问的样子吧. 第一问很显然(跟凤凰县探险队员一样显然),就是每次贪心选长度最大的满足条件的子序列,选不到就折返回来.所以折返的次数很明显就是选出子序列的个数 ...
- codeforces 1041 e 构造
Codeforces 1041 E 构造题. 给出一种操作,对于一棵树,去掉它的一条边.那么这颗树被分成两个部分,两个部分的分别的最大值就是这次操作的答案. 现在给出一棵树所有操作的结果,问能不能构造 ...
- Codeforces - 474D - Flowers - 构造 - 简单dp
https://codeforces.com/problemset/problem/474/D 这道题挺好的,思路是这样. 我们要找一个01串,其中0的段要被划分为若干个连续k的0. 我们设想一个长度 ...
- Codeforces Global Round 8 B. Codeforces Subsequences(构造)
题目链接:https://codeforces.com/contest/1368/problem/B 题意 构造最短的至少含有 $k$ 个 $codeforces$ 子序列的字符串. 题解 如下表: ...
- Codeforces 410C.Team[构造]
C. Team time limit per test 1 second memory limit per test 256 megabytes input standard input output ...
- Codeforces 716C[数论][构造]
/* CF傻逼构造题 某人要经过n回合游戏,初始分值是2,等级为1. 每次有两种操作 1.无条件,分值加上自己的等级数. 2.当目前的数字是完全平方数并且该数字开方以后是等级数加1的整数倍,那么可以将 ...
- Codeforces 1154D - Walking Robot - [贪心]
题目链接:https://codeforces.com/contest/1154/problem/D 题解: 贪心思路,没有太阳的时候,优先用可充电电池走,万不得已才用普通电池走.有太阳的时候,如果可 ...
- Tea Party CodeForces - 808C (构造+贪心)
Polycarp invited all his friends to the tea party to celebrate the holiday. He has ncups, one for ea ...
- New Roads CodeForces - 746G (树,构造)
大意:构造n结点树, 高度$i$的结点有$a_i$个, 且叶子有k个. 先确定主链, 然后贪心放其余节点. #include <iostream> #include <algorit ...
随机推荐
- poj2417 bsgs算法非逆元模板,用于求解A^x=B(mod C)的方程
参考博客 https://blog.csdn.net/clover_hxy/article/details/50683832关于欧拉定理推论的证明 https://www.cnblogs.com/as ...
- 如何把网址配置为http和https可以同时访问
1.打开iis7 ,找到具体站点 2.点击站点后右侧有个绑定按钮 3.点击绑定,增加https,设置端口,ssl选择 iis证书 4.找到ssl设置,要求证书不勾选,客户证书,忽略 5.如果右侧不显示 ...
- Eclipse中如何打开Map/Reduce Locations窗口
Window->Show View->Other->MapReduce Tools,双击打开
- CentOS6.9安装HDFS
1.安装依赖包 yum install -y gcc openssh-clients 2.升级glib2.14 升级glibc-2.14用到的rpm 下载地址:https://pan.baidu.co ...
- 【SpringBoot】常用注解
@EnableAutoConfiguration 启动自动装载:使用了这个注解之后,所有引入的jar的starters都会被自动注入.这个类的设计就是为starter工作的. @RestControl ...
- MUI组件四:选择器、滚动条、单选框、区域滚动和轮播组件
目录(?)[+] 1.picker(选择器) mui框架扩展了pipcker组件,可用于弹出选择器,在各平台上都有统一表现.poppicker和dtpicker是对picker的具体实现.*pop ...
- 【原创】java socket 和.net socket 通讯 demo
结束符协议"##" import java.io.BufferedReader; import java.io.IOException; import java.io.InputS ...
- npm淘宝镜像的设置和删除
设置 npm config set registry https://registry.npm.taobao.org npm config set disturl https://npm.taobao ...
- BZOJ3944 Sum 数论 杜教筛
原文链接http://www.cnblogs.com/zhouzhendong/p/8671759.html 题目传送门 - BZOJ3944 题意 多组数据(组数<=10). 每组数据一个正整 ...
- POJ1330Nearest Common Ancestors
去博客园看该题解 题意 第一行输入T,有T组数据. 对于每组数据,给出一棵树,先输入n,然后n-1行,每行两个数a,b,表示a是b的父亲:第n行输入两个数A,B表示询问A和B的最近公共祖先. 题解 L ...