zoukankan      html  css  js  c++  java
  • 【NOIP2013模拟联考5】休息(rest)

    Description
    休息的时候,可以放松放松浑身的肌肉,打扫打扫卫生,感觉很舒服。在某一天,某LMZ 开始整理他那书架。已知他的书有n 本,从左到右按顺序排列。他想把书从矮到高排好序,而每一本书都有一个独一无二的高度Hi。他排序的方法是:每一次将所有的书划分为尽量少的连续部分,使得每一部分的书的高度都是单调下降,然后将其中所有不少于2 本书的区间全部翻转。重复执行以上操作,最后使得书的高度全部单调上升。可是毕竟是休息时间,LMZ 不想花太多时间在给书排序这种事上面。因此他划分并翻转完第一次书之后,他想计算,他一共执行了多少次翻转操作才能把所有的书排好序。LMZ 惊奇地发现,第一次排序之前,他第一次划分出来的所有区间的长度都是偶数。

    Input
    第一行一个正整数n, 为书的总数。

    接下来一行n个数,第i个正整数Hi,为第i 本书的高度。

    Output
    仅一个整数,为LMZ 需要做的翻转操作的次数。

    Sample Input
    6

    5 3 2 1 6 4

    Sample Output
    3

    【样例解释】

    第一次划分之后,翻转(5,3,2,1),(6,4)。之后,书的高度为1 2 3 5 4 6,然后便是翻转(5,4)即可。

    Data Constraint
    对于10%的数据:n<=50
    对于40%的数据:n<=3000
    对于100%的数据:1<=n<=100000, 1<=Hi<=n
    .
    .
    .
    .
    .

    分析

    找出所有连续的单调下降序列,把它们全部翻转过来,每翻转一个序列,ans++,做完后,此为第一次交换。
    第一次交换后,剩下的就只能两两交换,所以只要求逆序对就好了。
    .
    .
    .
    .
    .

    程序:
    #include<iostream>
    #include<algorithm>
    using namespace std;
    long long a[100001],b[100001],n,w,t[100001],ans=0;
    
    void merge(long long a[],int l,int r)
    {
        if(l==r) return;
        int mid=(l+r)/2;
        merge(a,l,mid);
        merge(a,mid+1,r);
        int i=l,j=mid+1,p=l;
        while (i<=mid&&j<=r)
        {
            if (a[i]>a[j])
            {
                t[p++]=a[j++];
                ans+=mid-i+1;
            }
            else
            t[p++]=a[i++];
        }
        while(i<=mid) t[p++]=a[i++];
        while(j<=r) t[p++]=a[j++];
        for(i=l;i<=r;i++)
        a[i]=t[i];
    }
    
    
    void kp(int l,int r)
    {
        if (l>=r) return;
        int i=l,j=r,mid=a[(l+r)/2];
        do
        {
            while (a[i]<mid) i++;
            while (a[j]>mid) j--;
            if (i<=j)
            {
                swap(a[i],a[j]);
                i++;
                j--;
            }
        }while (i<=j);
    }
    
    int check()
    {
        for (int i=2;i<=n;i++)
        if (a[i]<a[i-1])
        {
            w=i;
            return 1;
        }
        return 0;
    }
    
    int main()
    {
        cin>>n;
        int tot=1;
        b[tot]=1;
        cin>>a[1];
        for (int i=2;i<=n;i++)
        {
            cin>>a[i];
            if (a[i]>a[i-1])
            {
                tot++;
                b[tot]=i;
            }
        }
        tot++;
        b[tot]=n;
        for (int i=2;i<=tot;i++)
        {
            kp(b[i-1],b[i]);
            ans++;
        }
        merge(a,1,n);
        cout<<ans;
    }
  • 相关阅读:
    LeetCode 230. 二叉搜索树中第K小的元素(Kth Smallest Element in a BST)
    LeetCode 216. 组合总和 III(Combination Sum III)
    LeetCode 179. 最大数(Largest Number)
    LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)
    LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
    LeetCode 106. 从中序与后序遍历序列构造二叉树(Construct Binary Tree from Inorder and Postorder Traversal)
    指针变量、普通变量、内存和地址的全面对比
    MiZ702学习笔记8——让MiZ702变身PC的方法
    你可能不知道的,定义,声明,初始化
    原创zynq文章整理(MiZ702教程+例程)
  • 原文地址:https://www.cnblogs.com/YYC-0304/p/9499917.html
Copyright © 2011-2022 走看看