第十八届浙大城市学院程序设计竞赛(同步赛)G

第十八届浙大城市学院程序设计竞赛(同步赛)G

大意

略。。

思路

很不错的题。。可惜我负数做下标没注意调了半天(

首先,看到两个长度相同的排列,就要想到有序化。

题中给了 (a) , (b) ,不妨假设存在一种函数关系,使 (f(b_i) = i)

将原序列变换,设 (c=f(a))(d=f(b)={1,2,3,...,n})

(如果观察改变前后 (a_i) 和对应 (b_i) 的位置差,你会发现这是完全不变的,因为值相等的位置,变换前后仍然相等)

容易得到,改变后的序列与原序列的答案一定是一致的。

再进行一步变形,令 (e_i = c_i - d_i)

不难发现实际 (e_i) 的值就是 (c_{i})(i) 的位置差值,也就是距离匹配位置的距离。

所以,(e) 中相同的数是一组,它们在进行移动操作 (-e_i) 次后正好与 (d) 中相应的数对应上。

大于零的数不用考虑,因为修改只能把数向前移动,而被移到结尾的数已经会被修改。

答案就是 (n-max(the num of same e_i)) ((c_ileq 0))

代码

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define ll long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)

const int mod = 1e9+7;
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;

int n;
int a[1001000];
int to[1001000];
int sum[1001000];

int main() {
    int r;
    cin >> n;
    for(int i=1; i<=n; i++) cin >> a[i];
    for(int i=1; i<=n; i++) cin >> r,to[r] = i;
    int mx = -inf_int;
    for(int i=1; i<=n; i++) a[i] = to[a[i]] - i;
    for(int i=n; i>=1; i--) if(a[i] <= 0) ++sum[-a[i]], mx = max(mx, -a[i]);
    int ans = n;
    for(int i=0; i<=mx; i++) ans = min(ans, n-sum[i]);
    cout << ans << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/ullio/p/14569318.html