Codeforces Round #555 (Div. 3) E. Minimum Array 【数据结构 + 贪心】

一 题面

  E. Minimum Array

二 分析

  注意前提条件:$0 \le  a_{i} \lt n$ 并且 $0 \le  b_{i} \lt n$。那么,我们可以在$a_{i}$中任取一个数进行分析,发现为满足字典序最小,在$b$中找到$n-a_{i}$就是最优解。

  接下来分析$b$,在$b$中是不一定找得到$n-a_{i}$的。所以需要分析如何找到此情况下的最优解。

  假设$a_{i} = 3$,$n = 4$,那么$b_{i}$对应的最优情况是$b_{i} = 1$,可以把所有$b_{i}$的所有取值情况分析以下:

$b_{i} = 0$  $(a_{i}+b_{i})\%n = 3$

$b_{i} = 1$  $(a_{i}+b_{i})\%n = 0$

$b_{i} = 2$  $(a_{i}+b_{i})\%n = 1$

$b_{i} = 3$  $(a_{i}+b_{i})\%n = 2$

  应该已经发现了规律了,就是以$n-a_{i}$为起点的一个循环。那么我们只要每次保证贪心取最小就可以了,这里需要运用$multiset$进行复杂度优化,但一定要注意查找的时候不能用$find$而要用$lower\_bound$,这样就可以解决了。

三 AC代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN = 2e5 + 15;
 4 int A[MAXN], B[MAXN];
 5 
 6 int main()
 7 {
 8     //freopen("input.txt", "r", stdin);
 9     int N, x;
10     multiset<int > ATree;
11     scanf("%d", &N);
12     for(int i = 0; i < N; i++)
13         scanf("%d", &A[i]);
14     for(int i = 0; i < N; i++)
15     {
16         scanf("%d", &B[i]);
17         ATree.insert(B[i]);
18     }
19     for(int i = 0; i < N; i++)
20     {
21         x = N - A[i];
22         auto p = ATree.lower_bound(x);
23         if(p == ATree.end() )
24             p = ATree.begin();
25         x = *p;
26         printf("%d%c", (x + A[i]) % N , i == N -1 ? '\n':' ');
27         ATree.erase(p);
28     }
29     return 0;
30 }

  

猜你喜欢

转载自www.cnblogs.com/dybala21/p/10778391.html