• BZOJ4240 有趣的家庭菜园(贪心+树状数组)


      显然相当于使序列变成单峰。给原序列每个数按位置标号,则要求重排后的序列原标号的逆序对数最少。考虑将数从大到小放进新序列,那么贪心的考虑放在左边还是右边即可,因为更小的数一定会在其两侧,与它自身放在哪无关。对于相同的数,一定可以将其安排至之间无逆序对,特判一下。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 300010
    int n,tree[N];
    long long ans=0;
    struct data{int x,i;
    }a[N];
    bool cmp(const data&a,const data&b)
    {
        return a.x>b.x;
    }
    void add(int k){while (k<=n) tree[k]++,k+=k&-k;}
    int query(int k){int s=0;while (k) s+=tree[k],k-=k&-k;return s;}
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4240.in","r",stdin);
        freopen("bzoj4240.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        for (int i=1;i<=n;i++) a[i].x=read(),a[i].i=i;
        sort(a+1,a+n+1,cmp);
        for (int i=1;i<=n;i++)
        {
            int t=i;while (t<n&&a[t+1].x==a[i].x) t++;
            for (int j=i;j<=t;j++) ans+=min(query(a[j].i),i-1-query(a[j].i));
            for (int j=i;j<=t;j++) add(a[j].i);
            i=t;
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    天啦噜!原来Chrome自带的开发者工具能这么用你知道么!
    JavaScript易错知识点整理
    2016年开源巨献:来自百度的71款开源项目
    前端js面试中的常见的算法问题
    详解JS跨域问题
    console 输出信息
    js身份证校验
    阻止页面回退
    pc端js常用方法
    js实现QQ、微信、新浪微博分享功能
  • 原文地址:https://www.cnblogs.com/Gloid/p/9833852.html
Copyright © 2020-2023  润新知