zoukankan      html  css  js  c++  java
  • HihoCoder

    描述

    对于一个长度为n的数列A,我们如下定义A的中位数med(A):

    当n是奇数时,A的中位数是第(n+1)/2大的数;当n是偶数时,A的中位数是第n/2大的数和第n/2+1大的数的平均值。  

    同时,我们如下定义A的前缀中位数和:

    S(A) = med(B1) + med(B2) + med(B3) + ... + med(Bn)

    其中Bi是A长度为i的前缀,即Bi=(A1, A2, A3 ... Ai-1, Ai),1 ≤ i ≤ n。  

    现在给定一个长度为n的数列X,我们希望通过将X中的数重新排列得到数列Y,使得S(Y)最大。

    例如对于X=(2, 3, 1, 5, 4),将X重新排列成Y=(5, 4, 3, 2, 1)会使得S(Y)最大,为5 + 4.5 + 4 + 3.5 + 3 = 20。

    为了描述方便,我们用一个1-n的排列P来表示重排的方法,即P满足XPi = Yi, 1 ≤ i ≤ n。例如在上面将X变成Y的重排中,P=(4, 5, 2, 1, 3)。

    你能找到使S(Y)最大重排方案P吗? 如果有多个P满足条件,输出字典序最小的P。

    对于两个长度为n排列P和Q,我们称P字典序小于Q当且仅当存在k满足

    1. 1 ≤ k ≤ n 且

    2. 对于任意i ≤ k,有Pi=Qi,且

    3. Pk < Qk

    输入

    第一行包含一个整数n (1 ≤ n ≤ 100000)  

    第二行包含n个整数,分别是X1, X2, ... Xn (1 ≤ Xi ≤ n)

    输出

    一行包含n个整数代表字典序最小的P

    样例输入
    5
    1 2 3 4 5
    样例输出
    5 4 1 3 2

    思路:大的数如果后放,是很难作为中位数的,所以大的数应当靠前放。 而在放了几个足够大的数后,我们考虑可以在中位数不变的情况下,从左到右放几个数,从而保证结果最大,而字典序最小。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=1000010;
    struct in{ int x,pos; }s[maxn];
    bool cmp(in w,in v){ return w.x==v.x?w.pos<v.pos:w.x>v.x; }
    int ans[maxn],used[maxn],pos;
    int main()
    {
        int N; scanf("%d",&N);
        rep(i,1,N) scanf("%d",&s[i].x),s[i].pos=i;
        sort(s+1,s+N+1,cmp); pos=1;
        rep(i,1,N){
            if(used[s[i/2+1].pos]) {
                while(used[pos]) pos++;
                ans[i]=pos; used[pos]=1;
            }
            else ans[i]=s[i/2+1].pos,used[s[i/2+1].pos]=1;
        }
        rep(i,1,N) printf("%d ",ans[i]);
        return 0;
    }
  • 相关阅读:
    2019年春总结作业
    第十二周编程总结
    第十一周编程总结
    第九周编程总结
    第八周编程总结
    第七周编程总结
    2019春第五周作业
    2019年春季学期第四周作业
    2019年春季学期第三周作业
    2019年春季学期第二周作业
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10212957.html
Copyright © 2011-2022 走看看