bzoj4240: 有趣的家庭菜园

又是调成sb的题啊。。。

下午三个多小时就交代给这两题代码还短得要死的题

一眼就是离散化,树状数组&&逆序对

然后又是搞了个WA的做法,枚举分界点

正解要贪心。(不用离散化。。。)

排序后判断当前分在左边和右边

看下那边逆序对少放那边

一个经常用到的结论:我们给原数组标上下表1...n,移动若干次后我们会得到一个新的下标序列,需要的搬运次数就是这个新序列的逆序对数。——CQzhangyu

sun dog

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;

struct node
{
    int x,id;
}a[310000];
bool cmp(node n1,node n2){return n1.x>n2.x;}
int lslen,ls[310000];

int s[310000];
int lowbit(int x){return x&-x;}
void change(int x,int k)
{
    while(x<=300100)
    {
        s[x]+=k;
        x+=lowbit(x);
    }
}
int getsum(int x)
{
    int ret=0;
    while(x>0)
    {
        ret+=s[x];
        x-=lowbit(x);
    }
    return ret;
}

int ln[310000],rn[310000];
int main()
{
    freopen("data.in","r",stdin);
    freopen("1.out","w",stdout);
    
    int n;
    scanf("%d",&n);lslen=n;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i].x), a[i].id=i, ls[i]=a[i].x;
        
    sort(ls+1,ls+lslen+1);
    lslen=unique(ls+1,ls+lslen+1)-ls-1;
    for(int i=1;i<=n;i++)
        a[i].x=lower_bound(ls+1,ls+lslen+1,a[i].x)-ls;
    
    sort(a+1,a+n+1,cmp);
    //----init------
    
    LL ans=0;int sum,tp;
    for(int i=1;i<=n;i=tp+1)
    {   
        sum=i-1;
        for(int j=i;a[i].x==a[j].x&&j<=n;j++)
        {
            int r=getsum(a[j].id-1);
            ans+=( LL(min(r, sum-r)) );
            tp=j;
        }
        for(int j=i;j<=tp;j++)change(a[j].id,1);
    }
    printf("%lld
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/AKCqhzdy/p/8876272.html