火柴排队

题目传送门

思路

我们需要让\(\sum_{i=1}^{n}(a_i-b_i)^2\)最小化,也就是等于\(0\),我们就需要让\(a\)序列和\(b\)序列所有元素对应相同。

我们先离散化一下,然后就求最少几个操作使得\(b\)序列转换为\(a\)序列。

我们再建立一个数组\(z\)

假设我们现在有离散化后的序列 \(a = \{4, 3, 1, 2\},b = \{1, 3, 2, 4\}\)

我们令\(z[a[i]]=b[i]\),相当于以\(a[i]\)为关键字对序列\(b[i]\)排序。

若序列\(a\)与序列\(b\)相等,那么此时\(z[a[i]]\)应该等于\(a[i]\)的,也就是\(z[i] = i\)

如果我们要\(a\)序列与\(b\)序列相同,则我们需要将\(z\)数组进行升序排列,那交换次数就是逆序对数

我使用的树状数组。

代码

#include <bits/stdc++.h>
using namespace std;
const long long MOD=99999997;
int n;
long long a[1000005],b[1000005],x[1000005],y[1000005],BIT[1000005],z[1000005];

bool cmp1(int x,int y) { return a[x]<a[y]; }

bool cmp2(int x,int y) { return b[x]<b[y]; }

int lowbit(int x) { return x & -x; }

void update(int k,int x) {
    for(int i=k;i<=n;i+=lowbit(i)) BIT[i]+=x;
    return ;
}

long long ask(int x) {
    long long ans=0;
    for(int i=x;i;i-=lowbit(i)) ans+=BIT[i];
    return ans;
}

int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        x[i]=y[i]=i;
    }
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    sort(x+1,x+n+1,cmp1);
    sort(y+1,y+n+1,cmp2);
    
    for(int i=1;i<=n;i++) z[x[i]]=y[i];
    long long ans=0;
    for(int i=1;i<=n;i++)  {
        ans+=i-ask(z[i])-1;
	    update(z[i],1);
        ans%=MOD;
    }
    printf("%lld",ans);
    return 0;
}
posted @ 2020-10-26 12:59  凌曦月lx  阅读(66)  评论(0编辑  收藏  举报