zoukankan      html  css  js  c++  java
  • CF1458D Flip and Reverse

    一个(01)串,可以如此操作:选择一个(0,1)出现次数相同的子串,将其翻转并取反。

    问经过任意次操作之后的字典序最小的字符串是什么。

    (nle 5*10^5)


    神仙转化。

    (0)视作(+1),把(1)视作(-1),做个前缀和(s_i)。连边((s_i,s_{i+1}))

    原来的字符串相当于这个图上的一条欧拉路径。

    思考下一个操作意味着什么:相当于找到欧拉路径上的一个环,将其反向并翻转。

    然后可以发现任意两个合法的欧拉路径可以通过这个操作转化,也就是:任意合法的欧拉路径都是能够形成的字符串。

    然后就是个图上找最小字典序欧拉路径的问题。

    两种做法:经典做法,直接递归做,回溯的时候把点丢入栈中,最后倒序输出栈中的点,做之前把边从小到大排序;或者也可以直接贪心选,但是要保证现在走的这条边不是桥。由于这题的特殊性,这个东西是比较好判断的。


    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 500005
    int n;
    char s[N];
    int _e[N+N];
    #define e(x) (_e[(x)+N])
    int q[N],k;
    void dfs(int x){
    	while (e(x)){
    		e(x)--;
    		dfs(x+1);
    	}
    	while (e(x-1)){
    		e(x-1)--;
    		dfs(x-1);
    	}
    	q[++k]=x;
    }
    int main(){
    	freopen("in.txt","r",stdin);
    	int T;
    	scanf("%d",&T);
    	while (T--){
    		scanf("%s",s+1);
    		n=strlen(s+1);
    		int x=0;
    		for (int i=1;i<=n;++i){
    			int y=x+(s[i]=='0'?1:-1);			
    			e(min(x,y))++;
    			x=y;			
    		}
    		dfs(0);
    		x=0;
    		for (--k;k;--k){
    			int y=q[k];
    			if (x+1==y)
    				putchar('0');
    			else
    				putchar('1');
    			x=y;
    		}
    		putchar('
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    socketserver
    socket进阶
    socket基础
    反射
    subprocess模块
    面向对象高级特性
    面向对象基础
    字典的高级特性
    *号的妙用
    logging模块
  • 原文地址:https://www.cnblogs.com/jz-597/p/14163674.html
Copyright © 2011-2022 走看看