• 【洛谷1338】末日的传说


    原题:

    咱这规律找滴彳亍不彳亍

    这个表是通过暴力枚举打的表,最左一列数字是逆序对个数,右边的是对应的字典序最小的排列,即所求答案

    现在可以来研究一下为什么会产生这种规律

    首先考虑一个特殊情况,当逆序对个数为m*(m-1)/2时,一个长度为m的递减序列就可以完成

    在递增序列的基础上,若使字典序最小,肯定尽可能只变动后面的数字,当逆序对个数为m*(m-1)/2时,只将后m个数字倒序排列是最优的

    因此就出现了图中粉色部分和黄色部分,当逆序对个数位于(m-1)*(m-2)/2和m*(m-1)/2之间时,只对后m个数字重排列

    那么如果逆序对个数为m*(m-1)/2+1,此时就不能只变动后m个数字,从右往左第m+1个数字必须发生变化

    若使字典序最小,因为前n-m-1个数字不变,则第n-m个(即从右往左第m+1个)数字应尽量小,而它又必须比n-m大(原来是n-m)

    因此此数字至少应该是n-m+1

    后m个数字中,比n-m+1小的只有n-m一个,因此n-m+1只能提供一组逆序对,还需要m*(m-1)/2个逆序对

    因此剩下的m个数字必须呈降序排列

    如果逆序对个数继续增加到m*(m-1)/2+2,则第n-m个数字为n-m+1也无法满足需求,因为后m个数字是降序的,已经达到最大逆序对

    因此第n-m个数字必须再次增加,变为n-m+2

    此时后m个数字中比n-m+2小的有n-m和n-m+1两个,还需要m*(m-1)/2个逆序对,于是后m个数字又必须降序排列……

    依此类推,每当逆序对个数+1,第n-m个数字就+1,这就形成了图中的红色部分

    剩余的数字降序排列,形成图中黄色和蓝色部分

    其中蓝色部分比红色部分大,黄色部分比红色部分小

    研究过规律的原理后,便可以找到一种正推出做法的思路(而不是靠打表观察或灵稽一动)

    当逆序对个数为0时,序列为递增序列,若逆序对个数+1,则交换最后两个数

    接下来再让逆序对+1,变为2,从左至右考虑每一位数字是否有必要改变

    结果发现倒数第3个数字不得不发生变化,因为后2个数字为降序排列

    于是让倒数第3个数字+1,变成n-1,然后发现n-1只能和n-2组成一组逆序对,还有2-1=1个逆序对需要解决

    而1=2*(2-1)/2,因此后2个数必须为降序,由此得到逆序对个数为2的解

    再让逆序对+1,因为后2个数必须为降序,所以倒数第3个数不得不变化

    让倒数第3个数字+1,变成n-2……

    类推上述步骤即可发现规律与构造方法

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int n,m;
     5 int main(){
     6     cin>>n>>m;
     7     int b=0;
     8     for(b=0;b<n && m>b;++b)  m-=b;
     9     for(int i=1;i<=n-b-1;++i)  printf("%d ",i);
    10     printf("%d ",n-(b-m));
    11     for(int i=1,j=n;i<=b-m;++i,--j)  printf("%d ",j);
    12     for(int i=1,j=n-(b-m)-1;i<=m;++i,--j)  printf("%d ",j);
    13     cout<<endl;
    14     return 0;
    15 }
    View Code
  • 相关阅读:
    常见的mysql查询命令
    Linux查看系统硬件信息命令汇总
    抓取页面上的email邮箱
    inotify+rsync实时同步【优化版本-转发】
    inotify+rsync做实时同步
    用配置文件里面的参数值替换yaml模板中的变量值【python】
    合并文件内容到另一个文件尾部[python]
    python farbric 主机/密钥列表配置
    python 项目环境包的名称和版本导出和导入
    sendmai.py
  • 原文地址:https://www.cnblogs.com/cdcq/p/12256459.html
Copyright © 2020-2023  润新知