Codeforces Round #812 (Div. 2) Editorial

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 ) (ii<j<kn) ,我们希望使 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+akaj次操作。( 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+akaj=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(2in1)满足 m a x ( [ 1 , i − 1 ] ) > a i max([1,i-1])>a_i max([1,i1])>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;
} 

内容参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值