1. 程式人生 > >2018QBXT刷題遊記(18)

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\n",sum);
    return 0;
}