• 51Node 1364--- 最大字典序排列(树状数组)


    51Node  1364--- 最大字典序排列(树状数组)

    基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
     收藏
     关注
    给出一个1至N的排列,允许你做不超过K次操作,每次操作可以将相邻的两个数交换,问能够得到的字典序最大的排列是什么?
    例如:N = 5, {1 2 3 4 5},k = 6,在6次交换后,能够得到的字典序最大的排列为{5 3 1 2 4}。
    Input
    第1行:2个数N, K中间用空格分隔(1 <= N <= 100000, 0 <= K <= 10^9)。
    第2至N + 1行:每行一个数i(1 <= i <= N)。
    Output
    输出共N行,每行1个数,对应字典序最大的排列的元素。
    Input示例
    5 6
    1
    2
    3
    4
    5
    Output示例
    5
    3
    1
    2
    4
    思路:先用a[]数组记录下输入的1~N的一个排列,并用p[]数组记录输入的排列中每个数的位置即:a[i]=x,p[x]==i;用树状数组c[]记录第i个位置的数距离前面要插入的距离,当第i个数移到前面后,后面的数移到前面要插入的距离减一,所以修改树状数组c[]的的值。注意:主要循环i:N~1,先将大的数往前移动,如果需要移动步数太多则跳过。

    代码如下:
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long LL;
    int N;
    int a[100005];
    int b[100005];
    int p[100005];
    int c[100005];
    
    int Lowbit(int t)
    {
        return t&(t^(t-1));
    }
    int sum(int x)
    {
        int sum=0;
        while(x>0)
        {
            sum+=c[x];
            x-=Lowbit(x);
        }
        return sum;
    }
    void adjust(int li,int t)
    {
        while(li<=N)
        {
            c[li]+=t;
            li=li+Lowbit(li);
        }
    }
    
    int main()
    {
        int K;
        while(scanf("%d%d",&N,&K)!=EOF)
        {
            memset(c,0,sizeof(c));
            for(int i=1;i<=N;i++)
            {
                int x;
                scanf("%d",&x);
                a[i]=x;
                p[x]=i;
                adjust(i,1);
            }
            int tot=1;
            for(int x=N;x>=1;x--)
            {
                if(a[p[x]]==0) continue;
                if(K<=0) break;
                int tmp=sum(p[x])-1;///因为前面已经有了tot-1个数,所以距离插入位置边近;
                if(tmp>K) continue;
                K-=tmp;
                b[tot++]=x;
                a[p[x]]=0;
                adjust(p[x],-1);
                if(tmp==0)///不能每次都跳到x=N,否则会超时;
                x=N;
            }
            for(int i=1;i<=N;i++)
            {
                if(a[i])
                    b[tot++]=a[i];
            }
            for(int i=1;i<=N;i++)
                printf("%d
    ",b[i]);
        }
        return 0;
    }
  • 相关阅读:
    PL/SQL Developer 和 instantclient客户端安装配置(图文)
    VirtualBox + Centos 使用NAT + Host-Only 方式联网
    zookeeper的安装
    Socket编程基础篇
    WebSocket教程(二)
    WebSocket教程(一)
    Js判断浏览器类型
    JVM内存模型
    js 正则去除指定的单词
    Java线上应用故障排查之一:高CPU占用
  • 原文地址:https://www.cnblogs.com/chen9510/p/5616129.html
Copyright © 2020-2023  润新知