思路
机翻害人,我还以为是 1 1 1 和 0 0 0 是对原序列排序,害得我比赛的时候都没对,恼。
首先,对于新加入的数字,我们可以先不确定是否有序,而是等到后续的 1 1 1 或 0 0 0 出现,再确定。
用 n u m num num 表示目前有多少数字,用 s o so so 表示确定有序的数字中最后一位的位置, n s o nso nso 表示确定无序的第一位数字的位置。
那么,我们可以分几种情况讨论:
-
操作 0 0 0。
- 如果满足 s o = n u m so=num so=num,那么目前所有数字都一定排序,所以无解。
- 如果满足 n u m < 2 num<2 num<2,按照题意,一定有序,所以无解。
- 其他情况都可以满足条件,此时对于 [ s o + 1 , n u m ] [so+1,num] [so+1,num] 的数字中有一个数字是无序的就行,这里选择最后一位,因为最后一位更容易被删除,后续满足条件的可能性更大,即 n s o = n u m nso=num nso=num,注意:如果 n s o nso nso 本来就有值,代表有更靠前的无序数字,则无需更新 n s o nso nso。
-
操作 1 1 1。
- 如果此时 n s o > 1 nso>1 nso>1,代表前面有数字一定无序,所以无解。
- 其他情况都可以满足条件,此时所有数都应该有序,即 s o = n u m so=num so=num。
-
操作 + + +,为了使后续操作满足条件可能性更大,所以选择添加未知数字,即仅 n u m + 1 num+1 num+1。
-
操作 − - −,先减 n u m num num,如果此时 n u m < s o num<so num<so,则也要把 s o so so 减一,如果此时 n u m < n s o num<nso num<nso,则代表无序的数字一定都被删了,所以更改 n s o nso nso 为 0 0 0。
AC code
#include<bits/stdc++.h>
using namespace std;
int T,n,num,so,flag,nso;
char ch[200005];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%s",ch+1),n=strlen(ch+1),nso=num=so=flag=0;
for(int i=1;i<=n;++i)
{
if(ch[i]=='+') ++num;
if(ch[i]=='-') --num,nso=(num<nso)?0:nso,so=min(so,num);
if(ch[i]=='1')
{
if(nso){flag=1;break;}
so=num;
}
if(ch[i]=='0')
{
if(num<2||so==num){flag=1;break;}
if(!nso) nso=num;
}
}
if(flag) printf("NO\n");
else printf("YES\n");
}
return 0;
}
文章讲述了如何通过逻辑分析和动态规划解决一个关于数字序列操作的问题,涉及有序与无序判断,以及如何在给定条件下添加或删除数字以保持序列有序。
4510

被折叠的 条评论
为什么被折叠?



