2017.2.18[codevs1170]NOIP2008提高组复赛T4双栈排序

体面不贴

这题一开始卡了我好久……策了好久贪心都判断不了无解情况……

直到看了题解才发现自己有多傻逼……

传送门:http://blog.csdn.net/kqzxcmh/article/details/9566813

题解写的很清楚这里就不赘述了。

两次AC,还行吧。

关键是我太蒟蒻……

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #define N 1010
 7 #define RG register
 8 #define inf 0x3f3f3f3f
 9 using namespace std;
10 char ans[N];
11 bool mat[N][N];
12 int n,top1,top2,top,topo,inn[N],col[N],dp[N],sta1[N],sta2[N];
13 inline int Min(RG const int &a,RG const int &b){return a>b?b:a;}
14 inline int gi(){
15     RG int x=0;RG char c=getchar();
16     while(c<‘0‘||c>‘9‘) c=getchar();
17     while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();
18     return x;
19 }
20 inline bool dfs(RG int now){
21     for (RG int i=1;i<=n;++i)
22     if(mat[now][i]){
23         if(!col[i]){
24         col[i]=3-col[now];
25         if(!dfs(i)) return 0;
26         }
27         else if(col[i]==col[now])
28                 return 0;
29     }
30     return 1;
31 }
32 inline void out(){
33     ++topo;
34     if(sta1[top1]==topo&&top1){
35     ans[++top]=‘b‘;
36     --top1;
37     }
38     else{
39     ans[++top]=‘d‘;
40     --top2;
41     }
42 }
43 inline void work(){
44     n=gi();dp[n+1]=sta1[0]=sta2[0]=inf;
45     for (RG int i=1;i<=n;++i) inn[i]=gi();
46     for (RG int i=n;i>=1;--i) dp[i]=Min(dp[i+1],inn[i]);
47     for (RG int i=1;i<n-1;++i)
48     for (RG int j=i+1;j<n;++j)
49         if(inn[j]>inn[i]&&dp[j+1]<inn[i])
50         mat[i][j]=mat[j][i]=1;
51     for (RG int i=1;i<=n;++i)
52     if(!col[i]){
53         col[i]=1;
54         if(!dfs(i)){
55         printf("0\n");
56         return;
57         }
58     }
59     for (RG int i=1;i<=n;++i){
60     if(col[i]<2){
61         while(inn[i]>sta1[top1]) out();
62         ans[++top]=‘a‘;
63         sta1[++top1]=inn[i];
64     }
65     else{
66         while(sta1[top1]==topo+1&&top1){
67             ans[++top]=‘b‘;
68             --top1;
69         ++topo;
70             }
71         while(inn[i]>sta2[top2]) out();
72         ans[++top]=‘c‘;
73         sta2[++top2]=inn[i];
74     }
75     }
76     while(top1||top2) out();
77     for (RG int i=1;i<=top;++i) printf("%c ",ans[i]);
78     putchar(‘\n‘);
79 }
80 int main(){
81     freopen("3114.in","r",stdin);
82     freopen("3114.out","w",stdout);
83     work();
84     fclose(stdin);
85     fclose(stdout);
86     return 0;
87 }

时间: 2024-10-08 09:37:40

2017.2.18[codevs1170]NOIP2008提高组复赛T4双栈排序的相关文章

洛谷-火柴棒等式-NOIP2008提高组复赛

题目描述 Description 给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0-9的拼法如图所示: 注意: 1. 加号与等号各自需要两根火柴棍 2. 如果A≠B,则A+B=C与B+A=C视为不同的等式(A.B.C>=0) 3. n根火柴棍必须全部用上 输入输出格式 Input/output 输入格式: 输入文件matches.in共一行,又一个整数n(n<=24). 输出格式: 输出文件mat

Vijos1605 NOIP2008 提高组T4 双栈排序 BFS

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - Vijos1605 题意概括 有1个1~n的排列,有2个栈,现在通过以下操作,使得出栈序列有序. 操作a 当前元素入栈<S1> 操作b 弹出S1栈顶元素 操作c 当前元素入栈<S2> 操作d 弹出S2栈顶元素 如果无法使得出栈序列有序,那么输出0. 否则输出满足条件的字典序最小的操作序列. 题解 首先我们可以证明,任意时刻,任意一个栈中的元素,一定满足自底向上呈降序. 如果不呈降序呢? 那么会

Noip2008提高组总结

Noip2008前三题是基础题,仔细一些都是可以AC的,第四题的证明很巧妙,但是看懂后代码其实很简单,感觉在这些大家都不屑去做的简单题中又学到了不少,四道题代码基本都是十几二十行就够了,渐渐感觉到,比代码和算法更重要的是思想与建模,觉得下阶段应该多注意培养自己的建模能力. T1:火柴棒等式 最简单的模拟题,首先记录下每种数字需要的火柴棒数,最后枚举验证即可. + ? 1 2 3 4 5 6 7 8 9 10 11 #include <cstdio> int main(){     int n,

NOIP2008提高组(前三题) -SilverN

此处为前三题,第四题将单独发布 火柴棒等式 题目描述 给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0-9的拼法如图所示: 注意: 加号与等号各自需要两根火柴棍 如果A≠B,则A+B=C与B+A=C视为不同的等式(A.B.C>=0) n根火柴棍必须全部用上 输入输出格式 输入格式: 输入文件matches.in共一行,又一个整数n(n<=24). 输出格式: 输出文件matches.out共一行,

2017.11.25【NOIP提高组】模拟赛A组

2017.11.25[NOIP提高组]模拟赛A组 T1 3467. [NOIP2013模拟联考7]最长上升子序列(lis) T2 3468. [NOIP2013模拟联考7]OSU!(osu) T3 3472. [NOIP2013模拟联考8]匹配(match) T1 有转移方程f[i]=max{f[j]}+1,a[j]<a[i] 可以用线段树+离散化维护这个方程,因为涉及以往状态可以用主席树维护 打太丑爆空间了 Code 1 #include<cstdio> 2 #include<c

2017.12.02【NOIP提高组】模拟赛A组

2017.12.02[NOIP提高组]模拟赛A组 T1 3555[GDKOI2014模拟]树的直径 T2 3542[清华集训2014]冒泡排序 T3 3486[NOIP2013模拟联考10]道路改建(rebuild) T1 树直径的一个性质,两棵树合并,形成新的树的直径的两个端点为原树中的四个端点之二. 可以用反证法证明.用此性质本题就变成了lca裸题了 Code #include<cstdio> #include<cstring> #include<cmath> #i

2017.12.09【NOIP提高组】模拟赛A组

2017.12.09[NOIP提高组]模拟赛A组 T1 3489. [NOIP2013模拟联考11]数列的GCD(gcd) T2 3500.[NOIP2013模拟联考15]物语(monogatari) T3 3501.[NOIP2013模拟联考15]消息传递(news) 吐槽:这次的题好像有点水啊,但最简单的第二题都给打挂啦!!(数组开小了) T1 本套题中最难的题.考虑dp 设f[i]是b[1],b[2]...b[N]的最大公约数的数目,g[i]是b[1],b[2]...b[N]的公约数的数目

NOIP2008 双栈排序

题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1不为空,将S1栈顶元素弹出至输出序列 操作c 如果输入序列不为空,将第一个元素压入栈S2 操作d 如果栈S2不为空,将S2栈顶元素弹出至输出序列 如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”.例如(1,3,2,4)就是一个“可

NOIP2008 双栈排序 染色+模拟

挺不错的一道题,首先可以知道若存在形如 k<i<j 但 a[k]<a[i]<a[j]这样的,那么i,j一定不能(从始至终不能)进入同一个栈 例如 2 3 1,若2 3进入同一个栈,那么1再进栈然后马上出栈,这时候,2没有办法在3之前出来. 所以对于这样的i,j我们连一条边,然后dfs染色,若染色中发现相邻点颜色相同,则无解,否则我们按照1,2,1,2的顺序染色. 确定了每一个数属于哪个栈后,用2个stack模拟一下就好了. #include <iostream> #in