Description

你有\(n\)个整数\(A_{i}\)和\(n\)个整数\(B_{i}\)。你需要把它们配对,即每个\(A_{i}\)恰好对应一 个\(Bp_{i}\)。要求所有配对的整数差的绝对值之和尽量小,但不允许两个相同的数配对。例如\(A=\lbrace 5,6,8 \rbrace\),\(B=\lbrace 5,7,8 \rbrace\),则最优配对方案是\(5\)配\(8\),\(6\)配\(5\),\(8\)配\(7\),配对整数的差的绝对值分别为\(2, 2, 1\),和为\(5\)。注意,\(5\)配\(5\),\(6\)配\(7\),\(8\)配\(8\)是不允许的,因为相同的数不许配对。

Input

第一行为一个正整数\(n\),接下来是\(n\)行,每行两个整数\(A_{i}\)和\(B_{i}\),保证所有\(A_{i}\)各不相同,\(B_{i}\)也各不相同。

Output

输出一个整数,即配对整数的差的绝对值之和的最小值。如果无法配对,输出\(-1\)。

Sample Input

3

3 65

45 10

60 25

Sample Output

32

HINT

\(30\%\)的数据满足:\(n \le 10^{4}\)

\(100\%\)的数据满足:\(1 \le n \le 10^{5}\),\(A_{i}\)和\(B_{i}\)均为\(1\)到\(10^{6}\)之间的整数。

难得又一道自己想出的题目。

首先如果没有相同的数字不能同时配对,那么排序之后两两配对一定是最优的。那么我们在满足题目限制一定也要尽可能的满足题目的限制,相邻两个进行交换。

我们令\(pos_{i}\)表示前第\(i\)个排序后数字相同配对的位置,\(f_{i,0/1}\)表示前\(i\)个数字相同的配对,使其合法的最小增加代价(\(0\)表示与前面的交换,\(1\)表示与后面的交换)。转移有这样以下的几个:

\[f_{i,1} = min(f_{i-1,0},f_{i-1,1})+calc(pos_{i},pos_{i}+1)
\]

当\(pos_{i-1} \ge pos_{i}-1\)时$$f_{i,0} = f_{i-1,0}+calc(pos_{i}-1,pos_{i})$$

否则$$f_{i,0} = min(f_{i-1,0},f_{i-1,1})+calc(pos_{i}-1,pos_{i})$$

产生分歧的原因是如果\(pos_{i-1} \ge pos_{i}-1\),那么如果\(i-1\)号非法配对与右边的交换,\(i\)号与左边的交换代价计算就会出错。

当\(i \ge 2\)并且\(pos_{i}=pos_{i-1}+1\),我们可以两个非法的进行交换,得到以下的转移:

当\(pos_{i-2} \ge pos_{i-1}-1\)时,$$f_{i,0} = min(f_{i,0},f_{i-2,0}+calc(pos_{i-1},pos_{i}))$$

否则$$f_{i,0} = min(f_{i,0},min(f_{i-2,0},f_{i-2,1})+calc(pos_{i-1},pos_{i}))$$

分歧的原因同上。

以上转移\(calc(a,b)\)为计算交换\(a,b\)位置增加代价的函数。

#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std; typedef long long ll;
#define inf (1LL<<60)
#define maxn 100010
int n,pos[maxn],tot; ll sum,A[maxn],B[maxn],f[maxn][2]; inline ll calc(int a,int b)
{
if (!a||!b) return inf; if (a > n||b > n) return inf;
return (abs(A[a]-B[b])+abs(A[b]-B[a]))-(abs(A[a]-B[a])+abs(A[b]-B[b]));
}
inline void dp()
{
memset(f,0x7,sizeof(f));
f[0][0] = f[0][1] = 0;
for (int i = 1;i <= tot;++i)
{
f[i][1] = min(f[i-1][0],f[i-1][1])+calc(pos[i],pos[i]+1);
if (pos[i-1]<pos[i]-1) f[i][0] = min(f[i-1][0],f[i-1][1])+calc(pos[i]-1,pos[i]);
else f[i][0] = f[i-1][0]+calc(pos[i]-1,pos[i]);
if (i >= 2&&pos[i] == pos[i-1]+1)
{
if (pos[i-2]<pos[i-1]-1) f[i][0] = min(f[i][0],min(f[i-2][0],f[i-2][1])+calc(pos[i-1],pos[i]));
else f[i][0] = min(f[i][0],f[i-2][0]+calc(pos[i-1],pos[i]));
}
}
} int main()
{
freopen("1237.in","r",stdin);
freopen("1237.out","w",stdout);
scanf("%d",&n); for (int i = 1;i <= n;++i) scanf("%lld %lld",A+i,B+i);
A[0] = A[n+1] = inf; pos[0] = -100;
sort(A+1,A+n+1); sort(B+1,B+n+1);
for (int i = 1;i <= n;++i)
{
sum += abs((A[i]-B[i]));
if (A[i] == B[i]) pos[++tot] = i;
}
dp(); printf("%lld",sum+min(f[tot][0],f[tot][1]));
fclose(stdin); fclose(stdout);
return 0;
}

BZOJ 1237 配对的更多相关文章

  1. BZOJ 1237 配对(DP)

    给出两个长度为n的序列.这两个序列的数字可以连边当且仅当它们不同,权值为它们的绝对值,求出这个二分图的最小权值完全匹配.没有输出-1. n<=1e5.用KM会TLE+MLE. 如果连边没有限制的 ...

  2. bzoj 1237 [SCOI2008]配对 贪心+dp

    思路:dp[ i ] 表示 排序后前 i 个元素匹配的最小值, 我们可以发现每个点和它匹配的点的距离不会超过2,这样就能转移啦. #include<bits/stdc++.h> #defi ...

  3. BZOJ 1786 配对(DP)

    如果我们直接令dp[i][j]为前i个位置第i个位置填j所产生的逆序对的最少数.这样是不满足无后效性的. 但是如果发现对于两个-1,如果前面的-1填的数要大于后面的-1填的数.容易证明把他们两交换结果 ...

  4. dp专练

    dp练习. codevs 1048 石子归并 区间dp #include<cstdio> #include<algorithm> #include<cstring> ...

  5. bzoj千题计划179:bzoj1237: [SCOI2008]配对

    http://www.lydsy.com/JudgeOnline/problem.php?id=1237 如果没有相同的数不能配对的限制 那就是排好序后 Σ abs(ai-bi) 相同的数不能配对 交 ...

  6. BZOJ 4205: 卡牌配对

    4205: 卡牌配对 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 173  Solved: 76[Submit][Status][Discuss] ...

  7. 图论(费用流):BZOJ 4514 [Sdoi2016]数字配对

    4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 820  Solved: 345[Submit][Status ...

  8. BZOJ 4514: [Sdoi2016]数字配对 [费用流 数论]

    4514: [Sdoi2016]数字配对 题意: 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数 ...

  9. BZOJ.4514.[SDOI2016]数字配对(费用流SPFA 二分图)

    BZOJ 洛谷 \(Solution\) 很显然的建二分图后跑最大费用流,但有个问题是一个数是只能用一次的,这样二分图两部分都有这个数. 那么就用两倍的.如果\(i\)可以向\(j'\)连边,\(j\ ...

随机推荐

  1. Memcached笔记——(四)应对高并发攻击【转】

    http://snowolf.iteye.com/blog/1677495 近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最 ...

  2. [TypeScript] Loading Compiled TypeScript Files in Browser with SystemJS

    TypeScript outputs JavaScript, but what are you supposed to do with it? This lesson shows how to tak ...

  3. 【转】学习Flex ActionScript 3.0 强烈推荐电子书

    学习Flex ActionScript 3.0 强烈推荐电子书 AdvancED ActionScript 3.0 Animation(<Make things  move>姐妹篇,强烈推 ...

  4. Apache Kafka: Next Generation Distributed Messaging System---reference

    Introduction Apache Kafka is a distributed publish-subscribe messaging system. It was originally dev ...

  5. CentOS更换python版本后,yum不可用的问题

    因为yum调用了python,他的启动程序/usr/bin/yum就是一个python脚本 yum是不兼容 Python 2.7的,所以yum不能正常工作,我们需要指定 yum 的Python版本 将 ...

  6. python学习笔记--Django入门二 Django 的模板系统

    为了使网站更干净简洁更容易维护,页面的设计和Python的代码必须分离开.我们可以使用Django的 模板系统 (Template System)来实现这种模式. 几个简单的模板标签(tag):   ...

  7. Xcode4快速Doxygen文档注释 — 简明图文教程

    转自:http://blog.csdn.net/totogo2010/article/details/9100767 准备2个文件: 文件一,ThisService.app 文件二,Doxygen.r ...

  8. Install-User.ps1

    Install-User.ps1 function Install-User { param( [Parameter()] [string]$ComputerName = $env:computern ...

  9. 大数据应用:五大地区喜新厌旧游戏APP类别之比较与分析

    今天,我们来分享点不一样的资讯.....游戏APP之喜新厌旧排行榜!! 前阵子笔者开发了一套系统可以用来收集亚洲五大地区上架APP的每日排名信息,希望观察出五大地区在APP上的喜好和使用程度之间的相异 ...

  10. 基于PHP的cURL快速入门

    cURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.最爽的是,PHP也支持 cURL 库.本文将介绍 cURL 的一些高级特性,以及在PHP中如 ...