zoukankan      html  css  js  c++  java
  • 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();
    }
    
  • 相关阅读:
    使用Eolinker拓展API设计
    如何记录API
    API设计
    【翻译】通过API主导的集成来证明您的业务未来
    从状态库迁移分布系统建设方式
    PostgreSql 查询某个模式下面的所有表
    迁移状态库的地市区县信息
    测开和开发的难度对比
    yum源的三种搭建方式
    Harbor实现容器镜像仓库的管理和运维
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12900843.html
Copyright © 2011-2022 走看看