zoukankan      html  css  js  c++  java
  • poj2085

    题意:给定n、m,求1~n的一个排列,逆序数对数为m,且该排列的字典序最小。

    分析:若逆序数对数为m,则每个数右侧比其大的数的个数之和应为k=n*(n-1) - m(正序数对数)。我们可以想象,如果把k拆分成若干个数字的和,并把这些数字随意分配给n个位置,来代表该位置右侧比该位置上的数字大的数的个数,那么这定能构成一个逆序数对数为m的排列。若想要字典序最小那么就要尽量把小的数往前放。小的数也就是其右侧比其大的数较多的数。如果用拆分k的方法,则应该给第一个位置分配最大的数,然后给第二个位置分配最大的数……然而每个位置分配的数是有限制的,因为对于位置i其右侧有n-i个数,也就是最多只能有n-i个数比它大,所以分配给该位置的数不能超过n-i。为了字典序最小我们就从左到右给每个位置分配其最大值,直至k被分配完了为止。这样就形成了一个字典序最小的逆序数对数为k的排列,但是我们并没有确切地知道这个排列是什么,只是知道了每个位置右侧比该位置上的数字大的数的个数。下面我们就来还原这个序列。这个分配k的方式有个特点,就是左面都是最大值,右面都是0。所以对于左面连续的最大值部分,我们只需要按照顺序将1~x填入其中即可(对于i位置,右侧有n-i个数字比它大,左侧所有的数字都比它小,那么它一定是i)。对于这个数组0与最大值的交界处会有一个不是最大值也不是0的数字y。我们把n-y填入答案的这个格,由于左侧数字都比它小,右侧有y个比它大的。然后对于所有的零只需将剩余的没有使用过的数字,按从大到小的顺序依次填入即可。

    View Code
    #include <iostream>
    #include
    <cstdio>
    #include
    <cstdlib>
    #include
    <cstring>
    usingnamespace std;

    #define maxn 50005

    longlong n, m;
    longlong f[maxn];
    bool vis[maxn];
    int ar[maxn];

    void work()
    {
    memset(vis,
    0, sizeof(vis));
    int x = n *(n -1) /2- m;
    int p =-1;
    for (int i =0; i < n; i++)
    {
    if (x >= n - i -1)
    {
    f[i]
    = i +1;
    x
    -= n - i -1;
    vis[f[i]]
    =true;
    }
    else
    {
    p
    = i;
    break;
    }
    }
    if (p ==-1)
    return;
    f[p]
    = n - x;
    vis[f[p]]
    =true;
    int s = n;
    for (int i = p +1; i < n; i++)
    {
    while (vis[s])
    s
    --;
    vis[s]
    =true;
    f[i]
    = s;
    }
    }

    void print()
    {
    printf(
    "%lld", f[0]);
    for (int i =1; i < n; i++)
    printf(
    " %lld", f[i]);
    putchar(
    '\n');
    }

    int main()
    {
    //freopen("t.txt", "r", stdin);
    while (scanf("%lld%lld", &n, &m), !(n ==-1&& m ==-1))
    {
    work();
    print();
    }
    return0;
    }
  • 相关阅读:
    01 Windows编程——Hello World
    图像处理基础知识
    集成IDE anaconda
    Python中的正则表达式
    Introduction of Machine Learning
    Linux命令——diff、patch
    sed & awk 概述
    Linux行编辑器——ed
    Linux命令——w、who、whoami、lastlog、last
    【问题】统计系统上有多少个用户
  • 原文地址:https://www.cnblogs.com/rainydays/p/2155440.html
Copyright © 2011-2022 走看看