CodeForces 578E Walking!

题意

略。

题解

好毒瘤啊,我最多就口胡第一问的样子吧。

第一问很显然(跟凤凰县探险队员一样显然),就是每次贪心选长度最大的满足条件的子序列,选不到就折返回来。所以折返的次数很明显就是选出子序列的个数 (-1)

考虑第二问,很明显不能暴力拼接子序列,这样很容易被 hack。具体方法剩下的题解有讲。

注意到找到的子序列可以按照开头和结尾分成 (4) 类:LLLRRLRR

首先有一个性质:可以将所有的 LR 拼在一起得到一个更长的 LRRL 同理。

接下来 LLRR 有一个特殊的作用,就是将一段 LR 和一段 RL 拼起来,类似于 L...RL...LR...LR...LR...RL...R。(这里两个字母中间三个点表示一段子序列)

但是有些时候,没有 LLRR,但是有 LRRL,这两段是无法拼起来的。难道我们就这样失败了吗?没有的事!

我们可以通过已经有的 LRRL 自己造一个 LLRR 出来。具体地话就是考虑 LRRL 中最后一个位置的关系。然后最后一个位置小的那个序列把最后一个位置给大的那个,然后 LR 就变成了 LL,而 RL 就变成了 RR

然后这题就做完了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=2e5+51;
ll n,tot,x,y,swp;
vector<ll>v[MAXN],vg[2],g[2][2];
char ch[MAXN]; 
inline ll read()
{
    register ll num=0,neg=1;
    register char ch=getchar();
    while(!isdigit(ch)&&ch!='-')
    {
        ch=getchar();
    }
    if(ch=='-')
    {
        neg=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch-'0');
        ch=getchar();
    }
    return num*neg;
}
int main()
{
    scanf("%s",ch+1),n=strlen(ch+1);
    for(register int i=1;i<=n;i++)
    {
        x=ch[i]=='R',vg[x^1].empty()?vg[x^1].push_back(++tot):(void)1;
        y=vg[x^1].back(),v[y].push_back(i);
        vg[x^1].pop_back(),vg[x].push_back(y);
    }
    printf("%d
",tot-1);
    for(register int i=1;i<=tot;i++)
    {
        g[v[i].size()&1][ch[v[i].back()]=='R'].push_back(i);
    }
    if(!g[0][0].empty()&&!g[0][1].empty()&&g[1][0].empty()&&g[1][1].empty())
    {
        x=g[0][0].back(),y=g[0][1].back();
        v[x].back()<v[y].back()?1:(swap(x,y),swp=1);
        v[x].push_back(v[y].back()),v[y].pop_back();
        g[0][0].pop_back(),g[0][1].pop_back(),swp?swap(x,y):(void)1;
        g[1][0].push_back(y),g[1][1].push_back(x);
    }
    if(g[1][0].size()!=g[1][1].size())
    {
        x=g[1][1].size()>g[1][0].size();
    }
    else
    {
        x=g[0][0].size()>g[0][1].size();
    }
    while(!g[0][x^1].empty())
    {
        for(register int i:v[g[0][x^1].back()])
        {
            printf("%d ",i);
        }
        g[0][x^1].pop_back();
    }
    while(!g[1][x].empty())
    {
        for(register int i:v[g[1][x].back()])
        {
            printf("%d ",i);
        }
        g[1][x].pop_back();
        while(!g[0][x].empty())
        {
            for(register int i:v[g[0][x].back()])
            {
                printf("%d ",i);    
            }
            g[0][x].pop_back();
        }
        x^=1;
    }
}
原文地址:https://www.cnblogs.com/Karry5307/p/13733909.html