zoukankan      html  css  js  c++  java
  • 【CF578E】Walking!(贪心)

    点此看题面

    • 给定一个长度为(n)的由LR构成的字符串(s)
    • 求构造一个排列(p_i),满足(forall iin[1,n),s[p_i] ot=s[p_{i+1}]),且满足(p_i>p_{i+1})(i)的个数最小。
    • (nle10^5)

    可以证伪的贪心

    考虑一个贪心,就是每次尽可能选取长度最大的符合条件的子序列,然后重复取若干次直至把整个序列取完。

    这一过程的实现是非常简单的,只要对LR两种字符各开一个(set),每次(lower\_bound)找后继就好了。

    然而,这个贪心是会被卡掉的。

    唯一一种(Hack)数据

    会被卡掉是毋庸置疑的,但能卡掉这个贪心的数据实际上只有一种。

    L为例,如果它选中的R后面全都是R,且在此之前还有R没有匹配,这时候贪心就会有问题。

    因为根据贪心的思路我们会先匹配后面的R再折回去找之前的LR,那么不如先回去匹配前面的R再一路匹配下来。

    只要特判一下这种情况就可以了。

    代码:(O(nlogn))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    using namespace std;
    int n,v[N+5];char s[N+5];set<int> S[2];
    I int Solve(RI x)//第一个字符为x
    {
    	RI i,t=0;for(i=1;i<=n;++i) S[s[i]=='R'].insert(i);//分字符插入set
    	#define Nxt(x,p) S[x].lower_bound(p)//后继
    	#define Mn(x) *S[x].begin()//最小值
    	RI p=0;for(i=1;i<=n;S[x].erase(v[i]=p),++i,x^=1)
    		p=Nxt(x,p)==S[x].end()?(++t,Mn(x)):*Nxt(x,p),//找到下一位
    		Nxt(x^1,p)==S[x^1].end()&&p^Mn(x)&&Mn(x)<Mn(x^1)&&(p=Mn(x),++t);//如果之后全是同样的字符,不如先选前面的
    	return t;
    }
    int main()
    {
    	RI i,t=0;for(scanf("%s",s+1),n=strlen(s+1),i=1;i<=n;++i) s[i]=='L'?++t:--t;//比较两种字符谁更多
    	for(printf("%d
    ",t?Solve(t==-1):Solve(s[1]=='R')),i=1;i<=n;++i) printf("%d ",v[i]);return 0;
    }
    
  • 相关阅读:
    java操作生成jar包 和写入jar包
    jboss配置jndi连接池
    windows 域的LDAP查询相关举例
    LDAP error Code 及解决方法
    HDU 6417
    CF1299D Around the World
    codechef Chef and The Colored Grid
    Educational Codeforces Round 82 (Rated for Div. 2)
    CF1237F Balanced Domino Placements
    CF1254E Send Tree to Charlie
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF578E.html
Copyright © 2011-2022 走看看