位元組跳動冬令營網路賽 - B - Origami
阿新 • • 發佈:2018-12-25
題目連結<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"); } }