zoukankan      html  css  js  c++  java
  • 1574 排列转换(鸽巢原理)

    1574 排列转换

    题目来源: CodeForces

    基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题

     

    现在有两个长度为n的排列p和s。要求通过交换使得p变成s。交换 pi 和 pj 的代价是|i-j|。要求使用最少的代价让p变成s。

    Input

    单组测试数据。 第一行有一个整数n (1≤n≤200000),表示排列的长度。 第二行有n个范围是1到n的整数,表示排列p。每个整数只出现一次。 第三行有n个范围是1到n的整数,表示排列s。每个整数只出现一次。

    Output

    输出一个整数,表示从排列p变到s最少要多少代价。

    Input示例

    样例输入1

    4

    4 2 1 3

    3 2 4 1

    Output示例

    样例输出1

    3

     

    //假如每次能选出两个没归位的 i,j,位置的数,使他们交换后,i,j 离目标位置更近了,重复此操作,便是最小代价变动了。

    证明必然存在这样的构造方式,

    假如 i 位置的目标为 j 位置,那么 j -- n 位置中,必然有一个目标为 1 -- i 位置。

    鸽巢原理,反证,先找到一组 i,j (i<j) ,且i,j位置之间的数都归位了,如果 i 目标位置为 j -- n ,那么必然 j -- n 有一个目标为 1 -- i ,交换 i ,j 即可。

    这样的 i ,j 必定能找到一组,不可能每对 i,j (i<j)目标都为同一边!

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 using namespace std;
     6 #define LL long long
     7 #define MOD 1000000007
     8 #define N 200005
     9 
    10 int n;
    11 int p[N];
    12 int s[N];
    13 int pos[N];
    14 
    15 int main()
    16 {
    17     scanf("%d",&n);
    18     for (int i=1;i<=n;i++)
    19     {
    20         scanf("%d",&p[i]);
    21         pos[ p[i] ] = i;
    22     }
    23 
    24     for (int i=1;i<=n;i++)
    25         scanf("%d",&s[i]);
    26 
    27     LL ans = 0;
    28     for (int i=1;i<=n;i++)
    29     {
    30         int x = pos[s[i]];
    31         ans=ans+abs(x-i);
    32     }
    33     printf("%lld
    ",ans/2);
    34 
    35     return 0;
    36 }
    View Code

     

  • 相关阅读:
    密码系统的安全性
    liboqs-量子安全密码算法开源C库
    密码基础知识(1)
    同态加密
    NTL 库函数
    以太坊相关的区块链知识
    53字符流中第一个不重复的字符
    基础小知识总结
    52表示数值的字符串 记忆
    HIHOcoder编程总结
  • 原文地址:https://www.cnblogs.com/haoabcd2010/p/7486981.html
Copyright © 2011-2022 走看看