[CF831D] Office Keys(二分,贪心)
题目链接:http://codeforces.com/contest/831/problem/D
题意:数轴上,n个人k把钥匙。所有人都要先拿到一把钥匙再去p点,一把钥匙只能一个人用,问最少需要多少时间。
最大流做最大匹配会TLE,所以GG。
很经典,二分时间,相当于每个人都有那么长的时间,然后处理出每个人刨去到重点时,能够到的最左最右端点,然后贪心地给每个人分配每个人能到的区间中最靠左的那把钥匙即可。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 typedef pair<LL, LL> pii; 6 const LL maxn = 1010; 7 const LL maxk = 2020; 8 LL n, k, p; 9 LL a[maxn], b[maxk]; 10 vector<pii> seg; 11 12 bool ok(LL tm) { 13 seg.clear(); 14 for(LL i = 1; i <= n; i++) { 15 LL rm = abs(a[i] - p); 16 if(rm > tm) return 0; 17 rm = (tm - rm) / 2; 18 LL lo = p, hi = a[i]; 19 if(lo > hi) swap(lo, hi); 20 lo -= rm, hi += rm; 21 seg.push_back(pii(lo, hi)); 22 } 23 sort(seg.begin(), seg.end()); 24 LL cnt = 1; 25 for(auto s : seg) { 26 while(cnt <= k && b[cnt] < s.first) cnt++; 27 if(cnt == k + 1 || b[cnt] > s.second) return 0; 28 cnt++; 29 } 30 return 1; 31 } 32 33 signed main() { 34 // freopen("in", "r", stdin); 35 while(~scanf("%lld%lld%lld",&n,&k,&p)) { 36 for(LL i = 1; i <= n; i++) scanf("%lld", &a[i]); 37 for(LL i = 1; i <= k; i++) scanf("%lld", &b[i]); 38 sort(a+1, a+n+1); sort(b+1, b+k+1); 39 LL lo = 0, hi = 10000000000LL; 40 LL ret = 0; 41 while(lo <= hi) { 42 LL mid = (lo + hi) >> 1; 43 if(ok(mid)) { 44 ret = mid; 45 hi = mid - 1; 46 } 47 else lo = mid + 1; 48 } 49 printf("%lld\n", ret); 50 } 51 return 0; 52 }