Codeforces 831D Office Keys 二分+贪心

来源:互联网 发布:神之浩劫数据迁移 编辑:程序博客网 时间:2024/05/27 21:01
题意:n个人在一条直线上,有终点p和k把钥匙,每把钥匙只能拿一次.
n,k<=2000,p<=1e9,问n个人同时出发拿了钥匙到达终点需要的最少时间?

二分答案,确定时间后能得到每个人拿钥匙的范围区间[l,r],接下来就是判定每个区间是否能配到一把钥匙?
因为区间长度相同 左端点排序后 最左区间拿最左钥匙即可.
#include <bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<ll,ll> ii;const int N=2e3+20;ll n,k,p,vis[N];ll a[N],b[N];vector<ii> seg;bool check(ll x){seg.clear();for(int i=1;i<=n;i++){if(abs(a[i]-p)>x)return false;ll add=(x-abs(a[i]-p))/2;ll l=p,r=a[i];if(l>r)swap(l,r);l-=add;r+=add;seg.push_back(ii(l,r));}sort(seg.begin(),seg.end());int cur=1;for(int i=0;i<seg.size();i++){while(cur<=k&&b[cur]<seg[i].first)cur++;if(cur==k+1||b[cur]>seg[i].second)return false;cur++;}return true;}int main(){while(cin>>n>>k>>p){for(int i=1;i<=n;i++)scanf("%I64d",&a[i]);for(int i=1;i<=k;i++)scanf("%I64d",&b[i]);sort(a+1,a+1+n);sort(b+1,b+1+k);ll l=0,r=2e15,ans=-1;while(l<=r){ll mid=(l+r)>>1;if(check(mid))r=mid-1,ans=mid;elsel=mid+1;}cout<<r+1<<endl;}return 0;}

也可以排序后设:dp[i][j] 前i个人用前j把钥匙最大时间最小为 最后一把钥匙最后一个人拿最优?





















原创粉丝点击