zoukankan      html  css  js  c++  java
  • 2021牛客寒假算法基础集训营2 F. 牛牛与交换顺序

    链接:https://ac.nowcoder.com/acm/contest/9982/F
    来源:牛客网

    牛牛有一个数组,数组元素是1到n的排列,即数组的值在1~n范围内,且每个数字仅出现1次。
    牛牛想要将该数组变为升序排列的,他可以进行如下的操作。

    首先他要确定一个长度k,k的范围在1~n之间。
    接下来他将会进行若干次操作。在每轮操作中他都可以选择一段长度为k的子数组,然后进行区间的翻转操作。

    他可以做任意次数的操作,但是要求他每次选择的子数组区间满足li≤li+1li≤li+1,并且区间长度等于一开始选定的k,也就是说一旦某一次操作选择了数组的某个位置进行区间翻转操作,下一次做区间翻转的位置将会比上一次更靠右。

    牛牛发现,并不总是存在一个k可以使得数组排序变为有序,请你告诉牛牛是否存在一个k能够在满足规则的情况下完成排序。

    输入描述:

    第一行输入一个正整数n(1≤n≤105)(1≤n≤105)表示数组的大小。
    接下来输出一行n个正整数表示一个排列,即每个数的大小范围在1到n且每个正整数仅出现一次。
    

    输出描述:

    如果存在至少一个k能够使牛牛完成排序,请先在一行中输出一个"yes",然后另起一行输出一个可以满足排序的k,要求k的范围在[1,n][1,n]之间,如果有多解,你可以输出任意一个。反之如果不存在任何一个k可以完成排序,请直接在一行输出一个"no"
    

    标程给的deque,但直接reverse也能过。没给k初始化导致WA到自闭QAQ

    首先要知道k若存在则唯一。因为题目中限制了每次操作的子数组左端点下标一定是单调递增的,因此假设1~p-1已经有序,如果a[p] != p的话则一定要换。设a[q] = p,那么第一次操作的区间一定是p~q,因为只有这样才能把p换到他应该在的位置。如果不换的话,之后操作区间的左端点一定大于p,就再也没机会了。

    因此遍历数组,找到第一个a[p] != p的位置,同时根据之前的pos数组找到p真正所在的下标,如此确定下来k的值,同时先把第一段区间reverse。之后要做的就是遍历数组,每当发现a[i] != i的情况就reverse,最后再遍历一遍判断是否有序。

    这种写法得用scanf或者关同步的cin或者快读优化(赛后数据加强了

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <vector>
    using namespace std;
    int n, a[100005], pos[100005], k = 1, num;
    int main()
    {
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            pos[a[i]] = i;
        }
        for (int i = 1; i <= n; i++)
        {
            if(a[i] != i)
            {
                k = pos[i] - i + 1;
                reverse(a + i, a + i + k);
                break;
            }
        }//然后判断这个k是否可行
        bool flag = 1;
        for (int i = 1; i <= n; i++)
        {        
            if(a[i] != i) 
            {
                reverse(a + i, a + i + k);
            }
        }
        for (int i = 1; i <= n; i++)
        {
            if (a[i] != i)
            {
                flag = 0;
                break;
            }
        }
        if(flag)
        { 
            cout << "yes" << endl;
            cout << k;
        }
        else cout << "no";
        return 0;
    }
    
  • 相关阅读:
    湘志恒善.NET 企业实训新学员必读手册
    周末电脑城有感硬件和软件价格的升降(实物图9.22更新)
    企业I期做项目之前的小例子
    商学院企业I班暑期作业 【2008年8月12日更新】
    项目公司机房升级
    android小应用帮美女更衣系列一(附源码)
    android小应用帮美女更衣系列二(附源码)
    @synthesize 和 @property
    VS2008下载地址和版本破解
    Android腾讯微薄客户端开发十三:提及篇(与我有关的微博)
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14369828.html
Copyright © 2011-2022 走看看