字节跳动冬令营网络赛 - B - Origami

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/84677530

题目链接<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");
    }
}

猜你喜欢

转载自blog.csdn.net/monochrome00/article/details/84677530
今日推荐