noip2013 火柴排队

(a-b)^2=a^2+b^2-2*a*b,所有a^2+b^2的和是一致的,就是最小化sigma{ai*bi};

先分析题意,发现a数组中最小的和b数组中最小的合在一起是最优的

进行归并排序,求出逆序对个数;

也可以用树状数组进行维护

c[i]表示i前面比他小的个数,

i-c[i]就是i位置的逆序对个数

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int ha=99999997;
int n;
struct hyq{
    int va,po;
}a[100010],b[100010];
int d[100010];
int c[400010];
long long ans;
bool cmp(hyq x,hyq y){
    return x.va<y.va;
}
int lowbit(int x){
    return x&(-x);
}
void update(int x,int v){
    while(x<=n){
        c[x]=(c[x]+v)%ha;
        x+=lowbit(x);
    }
}
int query(int x){
    int res=0;
    while(x>0){
        res=(c[x]+res)%ha;
        x-=lowbit(x);
    }
    return res;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i].va;
        a[i].po=i;
    }
    for(int i=1;i<=n;i++){
        cin>>b[i].va;
        b[i].po=i;
    }
    sort(a+1,a+n+1,cmp);
    sort(b+1,b+n+1,cmp);
    for(int i=1;i<=n;i++){
        d[a[i].po]=b[i].po;
    }
    for(int i=1;i<=n;i++){
        update(d[i],1);
        ans=(ans+i-query(d[i]))%ha;
    }
    cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/weixin_42759194/article/details/81809112