CF578E Walking!

Posted cjoiershiina-mashiro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF578E Walking!相关的知识,希望对你有一定的参考价值。

Link
有解的充要条件是( ext L)( ext R)的数量相差不超过(1)
不难证明初始位置一定是可以选择的初始位置中最靠前的那个。
下文的合法位置指的是尚未被走到的字符与当前位置不同的位置。
然后我们有一个简单的贪心,是每次选择在当前位置后面的最靠前的合法位置走过去,如果不存在就用(1)的花费走回序列中的第一个合法位置。
这种贪心会有一个反例:
假如当前我们在一个为( ext L)的位置,这个位置后面的合法位置全都是( ext R),并且序列第一个合法位置也是( ext R),那么我们这一步应该用(1)的花费走到序列的第一个合法位置。
加上这个特判之后这个做法就没有问题了。

#include<set>
#include<cstdio>
#include<vector>
#include<cstring>
const int N=100007,inf=1e9;
int n;char str[N];std::vector<int>ans;std::set<int>s1,s2;
int getid(){return *s1.begin()<*s2.begin()? 1:2;}
void solve()
{
    int cnt=0,now=2,pos=0,next=*s1.begin();
    for(int i=1;i<=n;++i)
	if(now==1)
	{
	    if(next==inf||(getid()==2&&*s1.lower_bound(next)==inf&&*s2.begin()!=next)) ++cnt,next=*s2.begin();
	    pos=next,s2.erase(pos),next=*s1.lower_bound(pos),now=2,ans.push_back(pos);
	}
	else
	{
	    if(next==inf||(getid()==1&&*s2.lower_bound(next)==inf&&*s1.begin()!=next)) ++cnt,next=*s1.begin();
	    pos=next,s1.erase(pos),next=*s2.lower_bound(pos),now=1,ans.push_back(pos);
	}
    printf("%d
",cnt);
    for(int x:ans) printf("%d ",x);
}
int main()
{
    scanf("%s",str+1),n=strlen(str+1),s1.insert(inf),s2.insert(inf);
    for(int i=1;i<=n;++i) (str[i]==‘L‘? s1:s2).insert(i);
    if(s1.size()<s2.size()||(s1.size()==s2.size()&&*s1.begin()>*s2.begin())) s1.swap(s2);
    solve();
}

以上是关于CF578E Walking!的主要内容,如果未能解决你的问题,请参考以下文章

CF 1036B Diagonal Walking v.2——思路

CF D. Walking Between Houses (贪心)

CF 1036 B Diagonal Walking v.2 —— 思路

codeforces cf edu round#50 B. Diagonal Walking v.2

如何从后台弹出片段

B. Diagonal Walking v.2