zoukankan      html  css  js  c++  java
  • 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;
        }
    }
    
  • 相关阅读:
    常用排序算法及java语言实现
    机器学习实战笔记(python3实现)01--概述
    笔试错题--(字符串常量池和JVM运行时数据区)
    笔试错题(典型题)
    java进阶--java网络编程
    01_Java基础_第1天(Java概述、环境变量、注释、关键字、标识符、常量)
    数据库3(DBUtils)
    数据库2(JDBC、DBUtils)
    数据库1(数据库、表及表数据、SQL语句)
    Linux的基本命令
  • 原文地址:https://www.cnblogs.com/Karry5307/p/13733909.html
Copyright © 2011-2022 走看看