Educational Codeforces Round 124 (Rated for Div. 2) C~D题
题意:
给定序列长度n,有上下两个序列a,b,每个序列的内部相邻的位置链接在一起,现在要新加一些边,保证无论删除两个序列中的哪一个位置,剩下的2 ∗ n − 1个数会在一个连通块内,新加一条a[i]到b[j]的边所需要花费为abs(a[i]-b[j]) ,问最小的代价
思路:
我们很容易得到,当初始呈现”环形“时,一定满足条件,即abs(a[1]-b[1])+abs(a[n]-b[n])abs(a[1]−b[1])+abs(a[n]−b[n])或abs(a[1]-b[n])+abs(a[n]-b[1])abs(a[1]−b[n])+abs(a[n]−b[1])
同时发现:
如果选择a b s ( a [ 1 ] − b [ 1 ] ) abs(a[1]-b[1])abs(a[1]−b[1])我们也可以再加上一条端点包括a [ n ] a[n]a[n]和一条端点包括b [ n ] b[n]b[n]的两条边
如果选择a b s ( a [ n ] − b [ n ] ) abs(a[n]-b[n])abs(a[n]−b[n])我们也可以再加上一条端点包括a [ 1 ] a[1]a[1]和一条端点包括b [ 3 ] b[3]b[3]的两条边
如果选择a b s ( a [ 1 ] − b [ n ] ) abs(a[1]-b[n])abs(a[1]−b[n])我们也可以再加上一条端点包括a [ n ] a[n]a[n]和一条端点包括b [ 1 ] b[1]b[1]的两条边
如果选择a b s ( a [ n ] − b [ 1 ] ) abs(a[n]-b[1])abs(a[n]−b[1])我们也可以再加上一条端点包括a [ 1 ] a[1]a[1]和一条端点包括b [ n ] b[n]b[n]的两条边
总之:两个序列的四角位置的点都需要作为某条新边的端点就行了
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define int long long #define endl '\n' const int N=2e5+10,M=1e3+10,INF=1e9+10; int n,T; int a[N],b[N]; int sta[N],stb[N]; int mx[N]; signed main(){ cin>>T; for(int t=1;t<=T;t++) { scanf("%lld",&n); for(ll i=1;i<=n;i++) scanf("%lld",&a[i]); for(ll i=1;i<=n;i++) scanf("%lld",&b[i]); mx[0]=min(abs(a[1]-b[1])+abs(a[n]-b[n]),abs(a[1]-b[n])+abs(a[n]-b[1])); mx[1]=mx[2]=mx[3]=mx[4]=1e18; for(ll i=1;i<=n;i++){ mx[1]=min(mx[1],abs(a[1]-b[i])); mx[2]=min(mx[2],abs(a[n]-b[i])); mx[3]=min(mx[3],abs(b[1]-a[i])); mx[4]=min(mx[4],abs(b[n]-a[i])); } ll ans=min(mx[0],mx[1]+mx[2]+mx[3]+mx[4]); ans=min(ans,abs(a[1]-b[1])+mx[2]+mx[4]);//a1连接b1 ans=min(ans,abs(a[n]-b[n])+mx[1]+mx[3]);//an连接b1 ans=min(ans,abs(a[1]-b[n])+mx[2]+mx[3]);//a1连接bn ans=min(ans,abs(a[n]-b[1])+mx[1]+mx[4]);//an连接b1 printf("%lld\n",ans); } return 0; }

浙公网安备 33010602011771号