A - Traveling Salesman Problem
由题目大意可知,所有的点都在 x x x 轴或者 y y y 轴上。
由此,最短的走法就是顺着某一方向走到底,然后换方向。
最后,平移得所走的轨迹是一个长方形,边长分别是 x x x 轴的最大距离和 y y y 轴的最大距离。
void solve()
{
int n;scanf("%d",&n);
int max_y=0,min_y=0,max_x=0,min_x=0;
for(int i=1;i<=n;++i)
{
int x,y;scanf("%d%d",&x,&y);
if(x==0)
{
if(y>max_y)max_y=y;
if(y<min_y)min_y=y;
}
else
{
if(x>max_x)max_x=x;
if(x<min_x)min_x=x;
}
}
int ans=2*(max_x-min_x+max_y-min_y);
printf("%d\n",ans);
return;
}
B. Optimal Reduction
我们定义 m a x ( [ l , r ] ) max([l,r]) max([l,r]),是 a l , a l + 1 , . . . , a r a_l,a_{l+1},...,a_r al,al+1,...,ar的最大整数
注意这里的 m a x ( [ l , r ] ) max([l,r]) max([l,r])和 m a x ( [ l , n ] ) max([l,n]) max([l,n])可以事先算出来。
考虑这个队列中下标三元组 ( i , j , k ) (i,j,k) (i,j,k), ( i ≤ i < j < k ≤ n ) (i \le i< j < k \le n ) (i≤i<j<k≤n) ,我们希望使 a i , a j , a k a_i,a_j,a_k ai,aj,ak通过一些操作都等于0,有两种情况:
a i > a j a_i > a_j ai>aj且 a j < a k a_j<a_k aj<ak,这将花费 a i + a k − a j a_i+a_k-a_j ai+ak−aj次操作。( a j a_j aj在中间,当其减到0时,就必须由 a i a_i ai与 a k a_k ak分开减)
其他的情况将花费 m a x ( a i , a j , a k ) max(a_i,a_j,a_k) max(ai,aj,ak)次。
而且:(下面为等价变形)
因为: a i + a k − a j = m a x ( a i , a k ) + m i n ( a i , a k ) − a j = m a x ( a i , a j , a k ) + m a x ( a i , a k ) − a j a_i + a_k- a_j=max(a_i,a_k)+min(a_i,a_k)-a_j=max(a_i,a_j,a_k)+max(a_i,a_k)-a_j ai+ak−aj=max(ai,ak)+min(ai,ak)−aj=max(ai,aj,ak)+max(ai,ak)−aj
又: m i n ( a i , a k ) − a j > 0 min(a_i,a_k)-a_j > 0 min(ai,ak)−aj>0
所以: m a x ( a i , a j , a k ) + m i n ( a i , a k ) − a j > m a x ( a i , a j , a k ) max(a_i,a_j,a_k)+min(a_i,a_k)-a_j > max(a_i,a_j,a_k) max(ai,aj,ak)+min(ai,ak)−aj>max(ai,aj,ak)。
由此可得,第一种情况要求 m a x ( a i , a j , a k ) + m i n ( a i , a k ) − a j max(a_i,a_j,a_k)+min(a_i,a_k)-a_j max(ai,aj,ak)+min(ai,ak)−aj次操作,而第二种情况只要求 m a x ( a i , a j , a k ) max(a_i,a_j,a_k) max(ai,aj,ak)次操作,所以当三元组满足第一种情况时,这个答案就不是最优的。
综上所述,
当存在一个数 i ( 2 ≤ i ≤ n − 1 ) i(2 \le i \le n-1) i(2≤i≤n−1)满足 m a x ( [ 1 , i − 1 ] ) > a i max([1,i-1])>a_i max([1,i−1])>ai且 a i < m a x ( [ i + 1 , n ] ) a_i<max([i+1,n]) ai<max([i+1,n])时
答案否定,输出"NO"。
反之,答案肯定,输出"YES"。
void solve()
{
pref[1]=a[1];
for (int i=2;i<=n;++i)
pref[i]=max(pref[i-1],a[i]);
suff[n]=a[n];
for (int i=n-1;i>=1;--i)
suff[i]=max(suff[i+1],a[i]);
flag=true;
for (int i=2;i<=n-1;++i)
if (pref[i-1]>a[i] && a[i]<suff[i+1])
flag=false;
return;
}