2018QBXT刷题游记(18)

【2018QBXT刷题游记】

Day4 TEST6

T3 game

【吐槽】这几天写了多少道game了!

【题目大意】长度为n的数列,第i次交换任意相邻元素需要付出i的代价。操作完的序列的丑陋度是B*逆序对个数,其中B是给定的常数。求丑陋度和操作所付出的代价之和最小值。

【冷静分析】继续在纸上写写画画,突然想起逆序对个数就是相邻交换恢复成有序序列的次数!所以只用统计出逆序对个数,判断一下什么时候i会大于b即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
const int MAXN=50005;
ll b,a[MAXN],tmp[MAXN],sum,ans;
int n;
void Merge(int l,int mid,int r){
    int i=l;
    int j=mid+1;
    int k=l;
    while(i<=mid&&j<=r){
        if(a[i]>a[j]){
            tmp[k++]=a[j++];
            ans+=mid-i+1;
        }
        else tmp[k++]=a[i++];
    }
    while(i<=mid)tmp[k++]=a[i++];
    while(j<=r) tmp[k++]=a[j++];
    for(int i=l;i<=r;i++)
        a[i]=tmp[i];
}
ll S(int x){return (ll)(1+x)*x/2;}
void Merge_sort(int l,int r){
    if(l<r){
        int mid=(l+r)>>1;
        Merge_sort(l,mid);
        Merge_sort(mid+1,r);
        Merge(l,mid,r);
    }
}
int main(){
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
    scanf("%d%lld",&n,&b);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    ans=0;
    Merge_sort(1,n);
    sum=b*ans;
    if(ans<=b){
    	sum=sum-ans*b+S(ans);
	}
	else{
		sum=sum-b*b+S(b);
	}
	printf("%lld
",sum);
    return 0;
}

原文地址:https://www.cnblogs.com/erutsiom/p/9905150.html