首页 > 代码库 > Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案

<style></style>

There are n people and k keys on a straight line. Every person wants to get to the office which is located on the line as well. To do that, he needs to reach some point with a key, take the key and then go to the office. Once a key is taken by somebody, it couldn‘t be taken by anybody else.

You are to determine the minimum time needed for all n people to get to the office with keys. Assume that people move a unit distance per 1 second. If two people reach a key at the same time, only one of them can take the key. A person can pass through a point with a key without taking it.

Input

The first line contains three integers nk and p (1 ≤ n ≤ 1 000, n ≤ k ≤ 2 000, 1 ≤ p ≤ 109) — the number of people, the number of keys and the office location.

The second line contains n distinct integers a1, a2, ..., an (1 ≤ ai ≤ 109) — positions in which people are located initially. The positions are given in arbitrary order.

The third line contains k distinct integers b1, b2, ..., bk (1 ≤ bj ≤ 109) — positions of the keys. The positions are given in arbitrary order.

Note that there can‘t be more than one person or more than one key in the same point. A person and a key can be located in the same point.

Output

Print the minimum time (in seconds) needed for all n to reach the office with keys.

Examples
input
2 4 50
20 100
60 10 40 80
output
50
input
1 2 10
11
15 7
output
7
Note

In the first example the person located at point 20 should take the key located at point 40 and go with it to the office located at point 50. He spends 30 seconds. The person located at point 100 can take the key located at point 80 and go to the office with it. He spends 50 seconds. Thus, after 50 seconds everybody is in office with keys.


  题目大意 一个走廊里有n个人和k个钥匙,办公室在位置p,假定每个人每秒走一米,问至少要到少时间才能使得所有人到达办公室(进入办公室必须要钥匙,并且拿到了钥匙就不能给别人)。

  题目要求最大值最小,十有八九都是二分答案,因此,求值问题被转化成判定问题,给定时间mid,判断是否能够使得所有人进入办公室。

  首先可以把每个人可以拿钥匙的区间求出来,然后按左端点排一道序(因为就算先将人按位置排序,也不能保证区间的长度一样,即不能保证左端点的单调性),接着开始贪心,让每个人尽量拿靠左的钥匙(当然你按右端点排序,让每个人拿尽量靠右的钥匙也可以),中间判断一下是否可行。(如果你高兴的话还可以写二分匹配,当然由于覆盖的都是连续的区间,因此也没这个必要)所以,先要按钥匙的位置排一次序。

  然后写这道题的时候发生了好玩的事情,第一次交上去Wrong Answer on test 8,然后我看错了Output和Answer,我还以为cf机子中毒,连续交了几次,最后恍然发现,看反了,内心是崩溃的,当发现把这道题A掉后,它的提交次数比Virtaul practise时提交的总次数还多。

  另外注意一点,二分的左端点应从0开始,比如,只有一个人1把钥匙,人站在办公室门口,钥匙在办公室门口。

Code

  1 /**  2  * Codeforces  3  * Problem#831D  4  * Accepted  5  * Time:15ms  6  * Memory:2100k  7  */   8 #include <iostream>  9 #include <cstdio> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #include <cstring> 14 #include <cstdlib> 15 #include <fstream> 16 #include <sstream> 17 #include <algorithm> 18 #include <map> 19 #include <set> 20 #include <stack> 21 #include <queue> 22 #include <vector> 23 #include <stack> 24 #include <cassert> 25 #ifndef WIN32 26 #define Auto "%lld" 27 #else 28 #define Auto "%I64d" 29 #endif 30 using namespace std; 31 typedef bool boolean; 32 const signed int inf = (signed)((1u << 31) - 1); 33 const signed long long llf = (signed long long)((1ull << 61) - 1); 34 const double eps = 1e-6; 35 const int binary_limit = 128; 36 #define smin(a, b) a = min(a, b) 37 #define smax(a, b) a = max(a, b) 38 #define max3(a, b, c) max(a, max(b, c)) 39 #define min3(a, b, c) min(a, min(b, c)) 40 template<typename T> 41 inline boolean readInteger(T& u){ 42     char x; 43     int aFlag = 1; 44     while(!isdigit((x = getchar())) && x != - && x != -1); 45     if(x == -1) { 46         ungetc(x, stdin);     47         return false; 48     } 49     if(x == -){ 50         x = getchar(); 51         aFlag = -1; 52     } 53     for(u = x - 0; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - 0); 54     ungetc(x, stdin); 55     u *= aFlag; 56     return true; 57 } 58  59 int n, m, p; 60 int *ps, *ks;  61  62 inline void init() { 63     readInteger(n); 64     readInteger(m); 65     readInteger(p); 66     ps = new int[(n + 1)]; 67     ks = new int[(m + 1)]; 68     for(int i = 1; i <= n; i++) 69         readInteger(ps[i]); 70     for(int i = 1; i <= m; i++) 71         readInteger(ks[i]); 72 } 73  74 pair<int, int>* ls; 75 boolean check(int mid) { 76     for(int i = 1; i <= n; i++) { 77         int dis = abs(ps[i] - p); 78         if(dis > mid)    return false; 79         dis = (mid - dis) >> 1; 80         int l = ps[i], r = p; 81         if(l > r)    swap(l, r); 82         l -= dis, r += dis; 83         ls[i] = pair<int, int>(l, r); 84     } 85 //    cout << mid << " " << ls[1].first << " " << ls[1].second << endl; 86     sort(ls + 1, ls + n + 1); 87     int i, fin; 88     for(i = 1, fin = 1; i <= n; i++, fin++) { 89         while(fin <= m && ks[fin] < ls[i].first)    fin++; 90         if((ls[i].second < ks[fin]) || fin > m) 91             return false; 92     } 93     return true; 94 }  95  96 inline void solve() { 97     sort(ks + 1, ks + m + 1); 98 //    sort(ps + 1, ps + n + 1); 99     ls = new pair<int, int>[n + 1];100     int l = 0, r = 2e9;101     while(l <= r) {102         int mid = l + ((r - l) >> 1);103         if(check(mid))    r = mid - 1;104         else l = mid + 1;105     }106     printf("%d", r + 1);107 }108 109 int main() {110     init();111     solve();112     return 0;113 }

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案