题意:太懒了,去原题看吧。
题解:最大值最小,明显的二分痕迹,于是果断二分最大值。check的话,可以比较明显看出是一个匹配问题,n个数字,共产生了n+1个空位,现在有m个数字要全部填进去,我们可以nm的建立数字-空位的边,然后单独再考虑一下最前最后两个空位,但是这样的匹配是n+1和m匹配,不能处理那些不填数字的空位,于是我们建立n+1-m个“空点”,某个空位如果不填数字也合法的时候,就网每个空点都连边,这样存在解就等价于存在完美匹配。由于是完美匹配,我们跑匈牙利的时候,某个点不存在匹配方案就可以提前返回false,不这样优化会超时。
Code:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;
typedef long long LL;
int A[maxn],B[maxn];
int n,T,m;
int a[maxn],b[maxn];
int vis[maxn];
int first[maxn],nxt[maxn*maxn],des[maxn*maxn],tot;
inline void addEdge(int x,int y){
tot++;
des[tot] =y;
nxt[tot] = first[x];
first[x] = tot;
}
int path(int u,int flag){
for (int t = first[u];t;t=nxt[t]){
int v = des[t];
if (vis[v]!=flag){
vis[v]=flag;
if (b[v]==-1||path(b[v],flag)){
a[u]=v;
b[v]=u;
return 1;
}
}
}
return 0;
}
bool maxMatch(){
memset(a,-1,sizeof a);
memset(b,-1,sizeof b);
memset(vis,-1,sizeof vis);
int res =0;
for (int i=0;i<=n;i++){
if (a[i]==-1){
if(path(i,i))continue;
else return false;
}
}
return true;
}
bool check(int x){
tot=0;
memset(first,0,sizeof first);
for (int i=1;i<n;i++){
int temp = abs(A[i-1]-A[i]);
if (temp<=x){
for (int k = m;k<=n;k++){
addEdge(i,k);
}
}
for (int j=0;j<m;j++){
int temp = max(abs(B[j]-A[i]),abs(B[j]-A[i-1]));
if (temp<=x){
addEdge(i,j);
}
}
}
for (int i=0;i<m;i++){
int temp = abs(A[0]-B[i]);
if (temp<=x){
addEdge(0,i);
}
temp = abs(A[n-1]-B[i]);
if (temp<=x){
addEdge(n,i);
}
}
for (int i=m;i<=n;i++){
addEdge(0,i);
addEdge(n,i);
}
return maxMatch();
}
void solve(){
scanf("%d%d",&n,&m);
int Amax =0;
int Amin = 0x3f3f3f3f;
int Bmax =0;
int Bmin = 0x3f3f3f3f;
for (int i=0;i<n;i++){
scanf("%d",A+i);
Amax = max(Amax,A[i]);
Amin = max(Amin,A[i]);
}
for (int i=0;i<m;i++){
scanf("%d",B+i);
Bmax = max(Bmax,B[i]);
Bmin = max(Bmin,B[i]);
}
LL l =0;
LL r = max(abs(Bmax-Amin),abs(Bmin-Amax));
while (r-l>1){
LL mid = l+r >>1;
if (check(mid)){
r = mid;
}else{
l = mid;
}
}
if (check(l)){
printf("%d\n",l);
}else{
printf("%d\n",r);
}
}
int main(){
cin>>T;
while (T--){
solve();
}
return 0;
}