zoukankan      html  css  js  c++  java
  • [校内训练19_09_06]排序

    题意

    一个这样的算法:

    int cnt=0;
    for(int i=1;i<=n;++i)
    {
        for(int j=i+1;j<=n;++j)
        {
            if(a[j]<a[i])
            swap(a[j],a[i]);
            ++cnt;
        }
    }

    现在你cnt和原始数组a,求cnt步数后a的结果。注意a是n排列。

    $1 leq n leq 10^6,1 leq cnt leq frac{n(n-1)}{2}$

    思考

    对于某个i,如果j从i+1循环到了n,那么含义就是将i~n中最小的数放到第i位上,剩下的访问过的向右循环位移一位(在访问过的数中循环位移)。

    如果说外层的i在1~k中都完全遍历了一边,那么含义就是将1~k放到最前面。

    如果我们从小到大依次插入数字i,可以发现,最后每个数字的相对位置是不会改变的。

    这样,我们模拟这个过程。首先确定每个数的位置在哪,将大小位1~k的位置扔到大根对中。接下来从k+1枚举到n,若数字i的位置比堆顶靠后,那么这个数的位置就不会有变化(因为比它小的数都在它之前)。否则这个数最后就会到堆顶的位置(注意是从k+1枚举到n,从小到大),将对顶弹出,把数字i的位置加入。

    最后将剩下的步数处理了。

    复杂度$O(nlogn)$

    代码

     1 // luogu-judger-enable-o2
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 typedef long long int ll;
     5 const int maxn=1E6+5;
     6 int n,a[maxn],b[maxn],where[maxn];
     7 ll cnt;
     8 void solve(int x)
     9 {
    10     if(x==0)
    11         return;
    12     priority_queue<int>Q;
    13     for(int i=1;i<=n;++i)
    14         where[a[i]]=i;
    15     for(int i=1;i<=x;++i)
    16     {
    17         b[i]=i;
    18         Q.push(where[i]);
    19     }
    20     for(int i=x+1;i<=n;++i)
    21     {
    22         if(where[i]>Q.top())
    23             b[where[i]]=i;
    24         else
    25         {
    26             b[Q.top()]=i;
    27             Q.pop();
    28             Q.push(where[i]);
    29         }
    30     }
    31     for(int i=1;i<=n;++i)
    32         a[i]=b[i];
    33 }
    34 int main()
    35 {
    36 //    freopen("sort.in","r",stdin);
    37 //    freopen("sort.out","w",stdout);
    38     ios::sync_with_stdio(false);
    39     cin>>n>>cnt;
    40     for(int i=1;i<=n;++i)
    41         cin>>a[i];
    42     for(int i=1;i<=n;++i)
    43     {
    44         if(cnt<=n-i)
    45         {
    46             solve(i-1);
    47             for(int j=i+1;j<=n;++j)
    48             {
    49                 if(a[j]<a[i])
    50                     swap(a[j],a[i]);
    51                 --cnt;
    52                 if(cnt==0)
    53                 {
    54                     for(int k=1;k<=n;++k)
    55                         cout<<a[k]<<" ";
    56                     cout<<endl;
    57                     return 0;
    58                 }
    59             }
    60         }
    61         else
    62             cnt-=n-i;
    63     }
    64     return 0;
    65 }
    View Code
  • 相关阅读:
    软件工程-个人最终总结
    结对编程—电梯调度
    第三周(第三作业)感想
    周三第二个作业
    VS2013安装和单元测试
    对京东的评价
    简单的四则运算
    迷茫的软件工程
    vlan 和 子网
    ECLIPSE的jar包和文件的导入导出
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/11553819.html
Copyright © 2011-2022 走看看