题目链接<https://ac.nowcoder.com/acm/contest/296/B>
题意:
在一张长度为n的纸片上从左到右写上1~n的数字。每次从左或从右反复折叠,使得最后只有一个单位的长度。这样从上到下就会得到一个序列。给出一串序列问能否最后折叠出来。
题解:
直接画一下纸张折叠最后形成的样式,就可以发现题目可以翻译成:给出左右两串区间,要求每一串区间之间可以包含,相离,但不能相交。排序后利用栈维护即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
struct Node{
int l,r;
Node(int l=0,int r=0):l(l),r(r){}
bool operator<(const Node a)const{
if(l==a.l) return r<a.r;
return l<a.l;
}
}a[2][N];
int tp[2];
int t[N],T;
bool check(){
sort(a[0]+1,a[0]+1+tp[0]);
sort(a[1]+1,a[1]+1+tp[1]);
stack<Node>st;
for(int i=1;i<=tp[0];i++){
while(!st.empty()){
Node tt=st.top();
if(a[0][i].r<tt.r) break;
if(a[0][i].l<tt.r&&a[0][i].r>tt.r) return false;
st.pop();
}
st.push(a[0][i]);
}
while(!st.empty()) st.pop();
for(int i=1;i<=tp[1];i++){
while(!st.empty()){
Node tt=st.top();
if(a[1][i].r<tt.r) break;
if(a[1][i].l<tt.r&&a[1][i].r>tt.r) return false;
st.pop();
}
st.push(a[1][i]);
}
return true;
}
int main()
{
scanf("%d",&T);
while(T--){
int n,x;
tp[0]=tp[1]=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x);
t[x]=i;
}
int sd=1;
for(int i=2;i<=n;i++){
int le=min(t[i],t[i-1]);
int ri=max(t[i],t[i-1]);
a[sd][++tp[sd]]=Node(le,ri);
sd=sd^1;
}
if(check()) printf("Yes\n");
else printf("No\n");
}
}