题面
有 n 个盘子。盘子被生产出来后,被按照某种顺序摞在一起。初始盘堆中如果一个盘子比所有它上面的盘子都大,那么它是安全的,否则它是危险的。称初始盘堆为A,另外有一个开始为空的盘堆 B。为了掩盖失误,生产商会对盘子序列做一些“处理”,每次进行以下操作中的一个:(1)将 A 最上面的盘子放到 B 最上面;(2)将 B 最上面的盘子给你。在得到所有 n 个盘子之后,你需要判断初始盘堆里是否有危险的盘子。
20%的数据保证 n<=8
80%的数据保证 n<=1,000
100%的数据保证 1<=n<=100,000,0<盘子大小<1,000,000,000 且互不相等
分析
可以抽象出其实是个判断是否是合法出栈序列的模型。
O(N2)做法:判断每个数后面比它小的数构成的序列是否递减(显然,一个较大的数被拿出来后,后面的数只能递减)
O(N)做法:维护一个最大值,只需要判断比最大值小的序列是否递减,当更换最大值的时候序列清空。
反正水,瞎搞也行。
代码
分段写了
- #include<bits/stdc++.h>
- using namespace std;
- #define N 100010
- #define RT register
- int n,ok,cnt,top;
- int a[N],tmp[N];
- template<class T>
- inline void read(T &x)
- {
- x=0;int f=1;static char ch=getchar();
- while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
- x*=f;
- }
- int main()
- {
- while(scanf("%d",&n)==1)
- {
- ok=1;
- for(RT int i=1;i<=n;i++)read(a[i]);
- if(n<=1000)
- {
- for(RT int i=1;i<=n;++i)
- {
- int x=a[i];cnt=0;
- for(RT int j=i+1;j<=n;++j)
- {
- if(a[j]>x)continue;
- tmp[++cnt]=a[j];
- }tmp[cnt+1]=0;
- for(RT int i=2;i<=cnt;++i)
- {
- if(tmp[i-1]>tmp[i]&&tmp[i]>tmp[i+1])continue;
- else {ok=0;break;}
- }
- if(ok==0)break;
- }
- if(ok)printf("Y ");
- else printf("J ");
- }
- else
- {
- top=0;
- for(RT int i=1;i<=n;++i)
- {
- if(a[i]>top)cnt=0,top=a[i];
- else
- {
- if(cnt==0||tmp[cnt]>a[i])tmp[++cnt]=a[i];
- else {ok=0;break;}
- }
- }
- if(ok)printf("Y ");
- else printf("J ");
- }
- }
- return 0;
- }