E、CSL 的魔法 【模拟】 (“新智认知”杯上海高校程序设计竞赛暨第十七届上海大学程序设计春季联赛)

题目传送门:https://ac.nowcoder.com/acm/contest/551#question

题目描述 

有两个长度为 n 的序列,a0,a1,,an1a0,a1,…,an−1和 b0,b1,,bn1b0,b1,…,bn−1。CSL 有一种魔法,每执行一次魔法,可以任意挑选一个序列并任意交换序列中两个元素的位置。CSL 使用若干次魔法,得到最终的序列 a 和 b,并且想要让 a0b0+a1b1++an1bn1a0b0+a1b1+…+an−1bn−1的值最小化。求解 CSL 至少使用多少次魔法,能够达到最小化的目标。

输入描述:

第一行有一个整数 n,表示序列的长度。

接下来两行,每行有 n 个整数,分别表示初始序列 a 和 b。

输入数据保证每个序列里的数两两不同。
 
2n1052≤n≤105
1ai,bi1091≤ai,bi≤109

输出描述:

在一行输出一个整数,表示最少使用的魔法次数。
示例1

输入

复制
2
1 2
1 2

输出

复制
1
示例2

输入

复制
2
1 2
2 1

输出

复制
0

 

解题思路:

注意一个bug点即可:

给出的a b 序列的数不一定相同。

所以对于 两个序列都要进行排序,然后map映射一下原序列每个数对应的位置,每个数的排名。

然后以其中一个序列为参考,扫一遍,最大的匹配另一个序列里最小的,不能匹配则交换序列里两个数的位置。

AC code:

 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 #define LL long long
 4 #define inc(i, j, k) for(int i = j; i <= k; i++)
 5 #define rep(i, j, k) for(int i = j; i < k; i++)
 6 #define mem(i, j) memset(i, j, sizeof(i))
 7 #define gcd(i, j) __gcd(i, j)
 8 using namespace std;
 9 const int MAXN = 2e5+10;
10 map<int, int>ida, idb, xa, xb;
11 int a[MAXN], b[MAXN], tpa[MAXN], tpb[MAXN];
12 
13 bool cmp(int a, int b)
14 {
15     return a > b;
16 }
17 int N;
18 
19 int main()
20 {
21     scanf("%d", &N);
22     inc(i, 1, N){ scanf("%d", &a[i]); tpa[i] = a[i]; xa[a[i]] = i;}
23     inc(i, 1, N){ scanf("%d", &b[i]); tpb[i] = b[i]; xb[b[i]] = i;}
24     sort(tpa+1, tpa+1+N);
25     inc(i, 1, N) ida[tpa[i]] = i;
26     sort(tpb+1, tpb+1+N, cmp);
27     inc(i, 1, N) idb[tpb[i]] = i;
28     int ans = 0;
29     inc(i, 1, N)
30     {
31         if(ida[a[i]] != idb[b[i]]){
32             ans++;
33             int nxtb = tpb[ida[a[i]]];
34             int nxt = xb[nxtb];
35             xb[b[i]] = nxt;
36             xb[b[nxt]] = i;
37             swap(b[i], b[nxt]);
38         }
39     }
40 
41     printf("%d\n", ans);
42     return 0;
43 }
View Code

 

posted @ 2019-04-07 14:19  莜莫  阅读(318)  评论(0编辑  收藏  举报