codeforces 920C【巧解】

这是一道非常简单的题,题目大意就是,给你一个从1-n的一个排列,再给你一个由0和1组成的串s,要求如果第i位出现了1 那么原先的排列中的第i个数和第i+1个数能进行交换,不限交换次数,问你最后能否使得该排列升序

一般我们的解题思路都是 我们去找连续的1存在的位置,然后给这一串数据排好序,再对处理过的串进行升序分析。
思路很简单,我们也很容易想到,而且这样的话时间复杂度也是O(nlogn)

当然对于这道题,我们还可以从另外的角度来看,我们试想一下,现在有n个数,如果中间有一段可以通过交换变成升序,那么我们可以知道对于这一段来说,第一个一定是最小的数,并且最后一个一定是最大的数,现在我们有一段区间[l,r] 如果这段序列已经升序排好,要想使得整个数列升序,我们必须满足 [1,l-1]中的最大值一定小于a[l],[r+1,n]中的最小值,一定大于a[r]
再可以进一步说, [1,l-1]中的最大值一定小于 [l,n]中的最小值,因此我们发现,我们只要对每一个不能交换的位置进行这样的判断,我们就可以知道这个序列是否升序
最后简化为,只要求[1,i]的最大值,和[i,n]的最小值

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<string>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=200000+50;
int a[maxn];
int mx[maxn];
int mn[maxn];
char s[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    scanf("%s",&s[1]);
    mx[0]=0;
    for(int i=1;i<=n;i++)
    {
        mx[i]=max(mx[i-1],a[i]);
    }
    mn[n+1]=INF;
    for(int i=n;i>=1;i--)
    {
        mn[i]=min(mn[i+1],a[i]);
    }
    for(int i=1;i<n;i++)
    {
        if(s[i]=='1')continue;
        if(mx[i]>mn[i+1])
        {
            puts("NO");
            return 0;
        }
    }
    puts("YES");
    return 0;

}
全部评论

相关推荐

10-14 23:01
已编辑
中国地质大学(武汉) Java
CUG芝士圈:虽然是网上的项目,但最好还是包装一下,然后现在大部分公司都在忙校招,十月底、十一月初会好找一些。最后,boss才沟通100家,别焦虑,我去年暑假找第一段实习的时候沟通了500➕才有面试,校友加油
点赞 评论 收藏
分享
11-05 07:29
贵州大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务