Problem A 钥匙

有$n$个人和$m$个钥匙在数轴上,人的坐标为$a_i$,钥匙的坐标为$b_i$

而门的坐标为$p$,要让所有人获得一把不同钥匙,并且到达门,最长时间最短是多少。

对于$100\%$的数据满足$10^3 \leq n \leq 10^3 , n \leq k \leq 2\times 10^3$

Solution : 

  对于部分数据,可以二分答案然后进行二分图匹配,实测可以通过$80\%$的数据。

  事实上,对上面算法的极限复杂度是$O(n^2 k log_2 10^9)$

  事实上,我们可以将$nk$中人和钥匙的配对方案求出,排序后,直接从小往大贪心。

  这样子复杂度是$O(n \times k \times (\ log_2 n + log_2 k))$的。

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e6+10;
int n,k,p,a[N],b[N];
inline int read() {
    int X=0,w=0; char c=0;
    while(c<'0'||c>'9') {w|=c=='-';c=getchar();}
    while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();
    return w?-X:X;
}
int calc(int i,int j) {
    if (a[i]<=b[j] && b[j]<=p) return p-a[i];
    if (a[i]<=p && p<=b[j]) return b[j]-a[i]+b[j]-p;
    if (b[j]<=a[i] && a[i]<=p) return a[i]-b[j]+p-b[j];
    if (b[j]<=p && p<=a[i]) return a[i]-b[j]+p-b[j];
    if (p<=a[i] && a[i]<=b[j]) return b[j]-a[i]+b[j]-p;
    if (p<=b[j] && b[j]<=a[i]) return a[i]-p;  
}
namespace Subtask1 {
    vector<int>E[N];
    bool vis[N];
    int pre[N];
    bool find(int u) {
        int sz = E[u].size();
        for (int i=0;i<sz;i++) {
            int v=E[u][i]; if (vis[v]) continue;
            vis[v]=true;
            if (pre[v]==-1 || find(pre[v])) {
                pre[v]=u;
                return true;
            }
        }
        return false;
    }
    int solve() {
        int ans = 0;
        memset(pre,-1,sizeof(pre));
        for (int i=1;i<=n;i++) {
            memset(vis,false,sizeof(vis));
            if (find(i)) ans++;
        }
        return ans;
    }
    bool check(int Mid) {
        for (int i=1;i<=n;i++) E[i].clear();
        for (int i=1;i<=n;i++)
         for (int j=1;j<=k;j++)
          if (calc(i,j)<=Mid) E[i].push_back(j);
        int ans = solve();
        return (ans==n);    
    }
    void main() {
        int l=0,r=2e9,ans;
        while (l<=r) {
            int mid = (l+r)>>1;
            if (check(mid)) r=mid-1,ans=mid;
            else l=mid+1; 
        }
        cout<<ans<<'\n';
    }
}
namespace Subtask2 {
    bool vis1[N],vis2[N];
    struct node {
        int u,v,val;
    }v[N];
    bool cmp (node a,node b) {
        return a.val<b.val;
    }
    void main() {
        int cnt = 0;
        for (int i=1;i<=n;i++)
         for (int j=1;j<=k;j++)
           v[++cnt]=(node){i,j,calc(i,j)};
        sort(v+1,v+1+cnt,cmp);
        int ans = 0 ;
        for (int i=1;i<=cnt;i++) {
            node tmp = v[i];
            if (vis1[tmp.u] || vis2[tmp.v]) continue;
            ans=max(tmp.val,ans);
            vis1[tmp.u] = vis2[tmp.v] = 1;
        }
        printf("%lld\n",ans);
    } 
} 
signed main() {
//  freopen("key.in","r",stdin);
    //freopen("key.out","w",stdout);
    n=read();k=read();p=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<=k;i++) b[i]=read();
    if (n*k <= 10000000/3/n)  Subtask1::main();
    else Subtask2::main();
    return 0;
}
A.cpp

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案