@description@

有 m 个城市围成一个圆环,编号为 1~m。

某公司有 n 个职员住在 m 个城市,依次住在编号为 a1, a2, ..., an 的城市(可能住在同一城市)。且该公司有 n 个工作场所,依次在 b1, b2, ..., bn(一样可以在同一城市)。

现在要将职员与城市一一匹配,使得每个职员的居所与工作场所距离之和最小,并输出方案。

Input

第一行两个整数 m, n(1 <= m <= 10^9, 1 <= n <= 200000),表示圆环上的城市个数以及职员个数。

第二行 n 个整数 a1, a2, ..., an(1 <= ai <= m),表示职员居住的城市编号

第三行 n 个整数 b1, b2, ..., bn(1 <= bi <= m),表示工作场所所在的城市编号。

Output

第一行输出最小距离总和。

第二行输出匹配方案,第 i 个数表示第 i 个职员工作的场所编号。

Examples

Input

10 3

1 5 5

10 4 6

Output

3

1 2 3

Input

10 3

1 4 8

8 3 6

Output

4

2 3 1

Note

第一个样例中,1 - 10, 5 - 4, 5 - 6 的距离都为 1。

第二个样例中,1 - 3, 4 - 6, 8 - 8 的距离分别为 2, 2, 0。

@solution@

巧妙地见过类似的原题。。。

然而我在考场上还是没有做出来,真是丢人。

先将 a, b 排好序。

首先将 bi 扩张成三倍,分别为 bi - m, bi, bi + m。则 ai 与 bj 之间在圆环上的距离肯定为 ai 到 bj - m, bj, bj + m 之中的某一个的数轴上的距离。

记这个扩张过后的 b 为 b‘。

假如一个方案中 ai 匹配 bx,aj 匹配 by,且 ai < aj, bx > by(即匹配出现交叉),则交换匹配变成 ai 匹配 by,aj 匹配 bx 会更优(分类讨论众多情况即可验证)。

同时还可以在原先的圆环上验证一个结论:如果 a1 匹配 b[x],则 a2 应依次匹配 b[x+1],a3 匹配 b[x+2],...。

贪心地得到了这两个结论后,我们最终有效的方案只有 2*n + 1 种。只要能有效地维护出每种方案的距离总和就可以解决这道题。

定义 ans[i] 表示 a1 匹配 i 的距离总和。

两个点 i, j 的距离定义为 |i - j|,其中 i >= j 时为 i - j,否则为 j - i。

一开始 a1 匹配 b1,匹配的点对之间距离总为 ai - bi。将 a1 对应的匹配往后移动时,ai - bj 就将变为 bj - ai。

于是对于每一个 ai,对一开始某个连续的区间的贡献为 +ai,对后面某个连续的区间的贡献为 -ai;bi 对一开始某个连续的区间的贡献 -bi,对后面某个连续的区间的贡献为 +bi。

找出那个变化的点(即 b[j] <= a[i] < b[j+1]),做一个差分即可。

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 200000;
const ll INF = (1LL<<60);
struct node{
int pos; ll key;
friend bool operator < (node a, node b) {
return a.key < b.key;
}
}a[MAXN + 5], b[3*MAXN + 5];
ll sum[3*MAXN + 5];
int res[MAXN + 5];
int n; ll m;
int main() {
scanf("%lld%d", &m, &n);
for(int i=1;i<=n;i++)
scanf("%d", &a[i].key), a[i].pos = i;
sort(a + 1, a + n + 1);
a[n + 1].key = INF;
for(int i=1;i<=n;i++)
scanf("%d", &b[i].key), b[i].pos = i;
sort(b + 1, b + n + 1);
for(int i=1;i<=n;i++) {
b[2*n + i] = b[n + i] = b[i];
b[i].key -= m, b[2*n + i].key += m;
}
int p = 1;
for(int i=1;i<=n;i++) {
while( b[p].key <= a[i].key ) p++;
sum[0] += a[i].key;
if( p - i + 1 <= 2*n + 1 )
sum[p - i + 1] -= 2*a[i].key;
}
p = 1;
for(int i=1;i<=3*n;i++) {
while( a[p].key < b[i].key ) p++;
sum[max(0, i - n + 1)] -= b[i].key;
if( i - p + 2 <= 2*n + 1 )
sum[i - p + 2] += 2*b[i].key;
sum[min(i + 1, 2*n + 2)] -= b[i].key;
}
int ans = 1;
for(int i=1;i<=2*n+1;i++) {
sum[i] += sum[i-1];
if( sum[i] < sum[ans] )
ans = i;
}
for(int i=1;i<=n;i++)
res[a[i].pos] = b[ans+i-1].pos;
printf("%lld\n", sum[ans]);
for(int i=1;i<=n;i++)
printf("%d ", res[i]);
}

@details@

当时在网上随便找了一个题解,改改改写写写结果怎样都过不了。

后来自己一写就过了 =_=。

@codeforces - 1214F@ Employment的更多相关文章

  1. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  2. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  3. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  4. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  5. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  6. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

  7. CodeForces - 261B Maxim and Restaurant

    http://codeforces.com/problemset/problem/261/B 题目大意:给定n个数a1-an(n<=50,ai<=50),随机打乱后,记Si=a1+a2+a ...

  8. CodeForces - 696B Puzzles

    http://codeforces.com/problemset/problem/696/B 题目大意: 这是一颗有n个点的树,你从根开始游走,每当你第一次到达一个点时,把这个点的权记为(你已经到过不 ...

  9. CodeForces - 148D Bag of mice

    http://codeforces.com/problemset/problem/148/D 题目大意: 原来袋子里有w只白鼠和b只黑鼠 龙和王妃轮流从袋子里抓老鼠.谁先抓到白色老鼠谁就赢. 王妃每次 ...

随机推荐

  1. 百度the big talk节目

    主要事件 2015-03-09期:硅谷峰会:智能机器人&对话沃兹尼亚克 2015-03-02期:硅谷峰会:创新金融和智能城市 2015-02-15期:硅谷峰会:数字生物学和数字医药 2015- ...

  2. HTML连载58-绝对定位的参考点以及注意事项

    一.绝对定位参考点 1.规律: (1)默认情况下所有的绝对定位的元素,无论有没有祖先元素,都会以body作为参考点. <style> .box1{ width: 300px; height ...

  3. org.hibernate.service.ServiceRegistryBuilder被弃用

    看视频教程是这样写的: //创建配置对象 Configuration config = new Configuration().configure(); //创建服务注册对象 ServiceRegis ...

  4. RHEL7系统安装方式

    RHEL7系统安装方式包括: 1. 手动安装(介质在本地): 此种方式你可以通过图形界面操作定制你所需安装系统的配置及所需软件包等 优点:直观 缺点:效率低下,配置的东西多时易犯错 此种方式仅适用于初 ...

  5. oracle定制定时执行任务

    1.引言 定制定时执行的任务有两种形式,系统级别和数据库级别, 从操作系统级别来讲, windows系统我们可以使用任务计划来实现, 对于winXP系统,设置步骤如下,开始---设置---控制面板-- ...

  6. linux显示进程的内存映射pmap

    pmap命令可以显示进程的内存映射,使用这个命令可以找出造成内存瓶颈的原因. # pmap -d PID 显示PID为47394进程的内存信息. # pmap -d 47394 输出样例: 47394 ...

  7. Linux下安装ssdb

    安装ssdb wget --no-check-certificate https://github.com/ideawu/ssdb/archive/master.zip unzip master cd ...

  8. 一个基于swoole的作业调度组件,已经实现了redis和rabitmq队列消息存储。

    https://github.com/kcloze/swoole-jobs 一个基于swoole的作业调度组件,已经实现了redis和rabitmq队列消息存储.参考资料:swoole https:/ ...

  9. 表格存储TableStore2.0重磅发布,提供更强大数据管理能力

    表格存储TableStore是阿里云自研的面向海量结构化和半结构化数据存储的Serverless NoSQL多模型数据库,被广泛用于社交.物联网.人工智能.元数据和大数据等业务场景.表格存储Table ...

  10. leetcode 235-290 easy

    235. Lowest Common Ancestor of a Binary Search Tree 公共的祖先必定大于左点小于右点,否则不断递归到合适. class Solution { publ ...