• P1155 [NOIP2008 提高组] 双栈排序


    考虑只有一个栈的话。对于三个数字

    [i<j<k,a_k<a_i<a_j ]

    那么进行栈排序的话,需要i比j先出栈,k比i,j先出栈,这就产生矛盾了。需要在增加一个栈来了。
    显然i,j不能在同一个栈进行排序。所以要分开
    我们对于这种情况,在i,j之间连边。跑二分图染色,染色失败则无解.

    这题还要求输出字典序最小的操作,push操作的优先级更高,只到栈不合法的时候才pop,就是栈顶到栈底不再单调递增的时候就是非法,要pop。再向第二个栈push的时候,我们要判断第一个栈能不能pop,这样字典序更小.最后按顺序模拟出栈

    const int N = 1e3 + 79;
    int n, a[N], color[N];
    
    std::stack<int>s[2];
    int pos(1);
    
    struct graph {
    	int head[N], tot = 1, next[N << 1], ver[N << 1];
    	inline void add(int a, int b) {
    		ver[++tot] = b;
    		next[tot] = head[a];
    		head[a] = tot;
    	}
    } G;
    int smin[N];
    int q[N];
    
    
    inline bool Pop(int id) {
    	if(s[id].size() && s[id].top() == pos) {
    		putchar(id ? 'd' : 'b');
    		s[id].pop();
    		putchar(' ');
    		++pos;
    		return true;
    	}
    	return false;
    }
    
    inline void Push(int x, int id) {
    	if(id == 1) {
    		while(Pop(0));
    	}
    	while(s[id].size() && s[id].top() < x) {
    		if(!Pop(id)) {
    			Pop(id ^ 1);
    		}
    	}
    	if(id == 1) {
    		while(Pop(0));
    	}
    	s[id].push(x);
    	putchar(id ? 'c' : 'a');
    	putchar(' ');
    }
    
    
    
    int main() {
    
    	read(n);
    	rep(i, 1, n) {
    		read(a[i]);
    	}
    	smin[n + 1] = n + 1;
    	drp(i, n, 1) {
    		smin[i] = min(smin[i + 1], a[i]);
    	}
    	memset(color, 0xff, sizeof color);
    	rep(i, 1, n) {
    		rep(j, i + 1, n) {
    			if(smin[j + 1] < a[i] && a[i] < a[j]) {
    				G.add(i, j);
    				G.add(j, i);
    			}
    		}
    	}
    
    	rep(i, 1, n) {
    		if(!~color[i]) {
    			q[q[0] = 1] = i;
    			color[i] = 0;
    			rep(kkk, 1, q[0]) {
    				int x = q[kkk];
    				repg(x) {
    					int y(G.ver[i]);
    					if(~color[y] && color[y] != (color[x] ^ 1)) {
    						puts("0");
    						return 0;
    					}
    					if(!~color[y]) {
    						q[++q[0]] = y;
    						color[y] = color[x] ^ 1;
    
    					}
    				}
    			}
    		}
    	}
    	rep(i, 1, n) {
    		Push(a[i], color[i]);
    	}
    
    
    	while(s[0].size() || s[1].size()) {
    		Pop(0);
    		Pop(1);
    	}
    	return 0;
    }
    

    本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15473224.html

  • 相关阅读:
    希尔伯特空间
    Java基础之类型转换总结篇
    超实用在线编译网站,编辑器
    3269: 万水千山粽是情
    Problem A: 李白打酒
    2370: 圆周率
    C语言fmod()函数:对浮点数取模(求余)
    C语言exp()函数:e的次幂函数(以e为底的x次方值)
    2543: 数字整除
    2542: 弟弟的作业
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15473224.html
Copyright © 2020-2023  润新知