zoukankan      html  css  js  c++  java
  • 计蒜客NOIP模拟赛4 D2T1 鬼脚图

    鬼脚图,又称画鬼脚,在日本称作阿弥陀签,是一种经典游戏,也是一种简易的决策方法,常常用来抽签或决定分配组合。

    下图就是一张鬼脚图,其包含若干条竖线和若干条横线。请注意,横线只能水平连接相邻的两条竖线,且 在同一高度只会有一条横线

    在图的上方,我们将这 n 条竖线依次标号为 1n。以数字 3 为例,它会沿着所在的竖线下降,期间如果 遇到横线就会移动到横线的另一端,最终降落至下面的第一条竖线。上图中还标出了另外几种数字的最终位置。奇特的是,开始时每条竖线上都有一个数字,而 最终每条竖线下还是有一个数字

    现在,相信你一定已经理解了鬼脚图的规则,那么我们想请你完成下面的两个任务——

    1. 读入一张有 n 条竖线和 m 条横线的鬼脚图,请你输出最下面一行的最终序列。

    2. 如果让你设计一个鬼脚图最终序列达到上面的效果,你 最少需要多少条横线

    输入格式

    第一行 2 个数字 n,m,表示竖线和横线的数量。

    第二行 m 个数字,依次表示从高到低的横线。数字 a 的意义为,在第 a(1≤a<n)条竖线和第 a+1 条竖线间存在一条横线。

    输出格式

    第一行 n 个数字,表示该鬼脚图的最终序列。

    第二行 1 个数字,表示最少需要多少条横线。

    数据范围

    对于 10% 的数据:n≤3,m≤5

    对于 20% 的数据:n≤4,m≤100

    对于 40% 的数据:n≤8,m≤1000

    对于 60%的数据:n≤1000,m≤5000

    对于 100%的数据:n≤100000,m≤1000000

    样例输入

    3 3
    1 2 1

    样例输出

    3 2 1
    3
    对于高度从大到小的横线,等价于在最终序列中交换
    最终序列开始与初始序列相同
    然后模拟,交换横线端点的值

    第二问,要用最少步数得到
    显然就是最终序列的逆序对数
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 int n,m,a[100001],t[1000001];
     7 long long ans;
     8 void partition(int l,int r)
     9 {
    10     if (l>=r)
    11         return;
    12     int mid=(l+r)/2;
    13     partition(l,mid);
    14     partition(mid+1,r);
    15     int i=l,j=mid+1,k=l;
    16     while(i<=mid&&j<=r)
    17     {
    18         if(a[i]>a[j])
    19         {
    20             ans=(ans+mid-i+1);
    21             t[k]=a[j];
    22             k++;
    23             j++;
    24         }
    25         else
    26         {
    27             t[k]=a[i];
    28             k++;
    29             i++;
    30         }
    31     }
    32     while(i<=mid)
    33     {
    34         t[k]=a[i];
    35         k++;
    36         i++;
    37     }
    38     while(j<=r)
    39     {
    40         t[k]=a[j];
    41         k++;
    42         j++;
    43     }
    44     for(i=l; i<=r; i++)
    45         a[i]=t[i];
    46 }
    47 int main()
    48 {int i,x;
    49     cin>>n>>m;
    50     for (i=1;i<=n;i++)
    51     a[i]=i;
    52     for (i=1;i<=m;i++)
    53     {
    54         scanf("%d",&x);
    55         swap(a[x],a[x+1]);
    56     }
    57     for (i=1;i<=n;i++)
    58         if (i<n)
    59         printf("%d ",a[i]);
    60  else cout<<a[i];
    61  partition(1,n);
    62  cout<<endl<<ans;
    63 }
  • 相关阅读:
    个人总结21
    个人总结08
    个人总结07
    构建之法读后感01
    学习进度表 03
    四则运算3
    求最大值
    学习进度表02
    四则运算 2
    学习进度表01
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7592087.html
Copyright © 2011-2022 走看看