[校内训练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
原文地址:https://www.cnblogs.com/GreenDuck/p/11553819.html