Rails poj-1363
题目大意:判断一个序列是否是1~n的合法出栈序列。
注释:$1le nle 10^4$。
想法:开始想到一种想法。
对于一段序列来讲,显然从首元素开始的连续小于尾元素的序列必定为合法出栈序列,所剩下的数所组成的序列也必为合法出栈序列。
黄色序列中所有数小于尾元素,不小于全序列最小值(废话),而且必定为全队最小值到尾元素-1的一个排列。绿色序列同理。
然后,我们递归处理,先判断前面的黄色序列是否是合法的全排列,绿色序列是否是合法的全排列,然后递归处理。
但是,EdwardFrog有一种更显然的方法。我们进行模拟:
根据题目中的要求,如果当前第i个数小于等待进栈的数,显然它仍在栈里,如果栈首不是它,整个序列就是不合法的。反之,弹出。
如果第i个数大于等待进栈的数,我们连续的进栈,使得它刚好是栈首,此时弹出。
时间复杂度O(n)
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> using namespace std; int sta[1010]; int a[1010]; int head,k; void original() { memset(sta,0,sizeof sta); memset(a,0,sizeof a); head=0; k=1; } int main() { int n; while(~scanf("%d",&n)) { if(!n) return 0; // int n; // cin >> n; while(1) { original(); bool nxt=false; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i]==0) { nxt=true; break; } } if(nxt) break; bool flag=true; for(int i=1;i<=n;i++) { if(a[i]<k) { if(sta[head]!=a[i]) { printf("No "); flag=false; break; } else { head--; continue; } } else if(a[i]==k) k++; else { while(k<=a[i]) { sta[++head]=k; k++; } head--; } } if(flag)printf("Yes "); } puts(""); } return 0; }
小结:想到一个不可描述,但是觉得贼牛逼的做法时,不妨往简单想一想,毕竟所有的题目都是有简单的点构成的。