码迷,mamicode.com
首页 > 其他好文 > 详细

P1966 火柴排队

时间:2020-03-07 21:08:27      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:using   这不   最大的   ios   size   strong   use   证明   www   

P1966 火柴排队

求逆序对+数学

题意描述

有 a,b 两个数列,它们的距离为∑(ai-bi)2。

每列中相邻的两个数均可进行交换,求至少交换多少次,可以使 a,b 的距离最短。

看不懂你这题就别做了。

算法分析

首先你应该知道:顺序和≥乱序和≥逆序和(好像没有什么关系)

然后你应该知道它的证明方法,然后你就可以证出来这道题了。

但在证明之前,我们先感性地思考一下:a,b 数列中最大的相减,次大的相减…,次小的相减,最小的相减距离最小。

证明:A1>A2,B1>B2那么(A1-B1)2+(A2-B2)2<(A1-B2)2+(A2-B1)2。

假设(A1-B1)2+(A2-B2)2>(A1-B2)2+(A2-B1)2

A1^2 -2*A1*B1+B1^2+A2^2 -2*A2*B2+B2^2>A1^ 2-2*A1*B2+B2^2+ A2^ 2-2*A2*B1+B1^2

? 2*A1*B1+2*A2*B2<2*A1*B2+2*A2*B1

? A1*B1+A2*B2<A1*B2+A2*B1

? A1(B1-B2)<A2(B1-B2)

? A1<A2

得出矛盾,所以假设不成立。

证毕。

好了,这道题目的精华在于对于新建序列

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

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

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

那么也就是说如果我们想让序列 a 与序列 b 相等,那么我们需要让 q 升序排列。

问题就变为,将原本乱的 q 序列升序排列的最少交换次数。

诶,这不就是逆序对吗?

所以用归并排序求解即可。

代码实现

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define maxn 100010
#define mod 99999997
using namespace std;

int n,ans=0;
int c[maxn],q[maxn];
struct node{
   int num;//序号
   int big;//数据
}a[maxn],b[maxn];

bool cmp(node x,node y){
   return x.big<y.big;
 }

void init(){
   scanf("%d",&n);
   for(int i=1;i<=n;i++){
     scanf("%d",&a[i].big);
     a[i].num=i;
   }
   for(int i=1;i<=n;i++){
     scanf("%d",&b[i].big);
     b[i].num=i;
   }
   sort(a+1,a+n+1,cmp);
   sort(b+1,b+n+1,cmp);
   for(int i=1;i<=n;i++) q[a[i].num]=b[i].num;
   return;
 }

void work(int l,int r){
   if(l==r) return;
   int mid=(l+r)>>1;
   work(l,mid);work(mid+1,r);

int i=l,j=mid+1,k=l;
   while(i<=mid&&j<=r){
     if(q[i]<=q[j]) c[k++]=q[i++];
     else{
       c[k++]=q[j++];
       ans+=(mid-i+1)%mod;
       ans%=mod;
     }
   }
   while(i<=mid) c[k++]=q[i++];
   while(j<=r) c[k++]=q[j++];
   for(int p=l;p<=r;p++) q[p]=c[p];
 }

int main(){
   init();

  memset(c,0,sizeof(c));
   work(1,n);
   printf("%d\n",ans%mod);
   //system("pause");
   return 0;
}

结语

OI靠数学。

P1966 火柴排队

标签:using   这不   最大的   ios   size   strong   use   证明   www   

原文地址:https://www.cnblogs.com/lpf-666/p/12436396.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!