1 条题解

  • 0
    @ 2026-5-3 7:51:16

    思路

    通过观察样例和阅读题面,我们发现了以下性质。

    • 图像的紧凑性只取决于 x×yx \times y 的值。

      这里的 xx 是在竖直方向上距离最远的点之间的格子数。

      这里的 yy 是在水平方向上距离最远的点之间的格子数。

    • 向上平移与向下平移本质上是一样的,只会改变图像竖直方向上的相对位置并改变 xx 的值。

      向左平移与向右平移本质上是一样的,只会改变图像水平方向上的相对位置并改变 yy 的值。

      两类操作互不影响,可以分开来看。

    • 根据第二条,可以得出达到最小紧凑性所需的最小按钮点击次数取决于 sumx+sumysumx + sumy

      sumxsumx 是达到当前 xx 值所需的最小步骤。

      sumysumy 是达到当前 yy 值所需的最小步骤。

    根据第二条性质,我们知道向上(或向下)和向左(或向右)两类操作互不影响,可以分开来看。以向上(或向下)操作为例。

    因为 xx 的值只取决于竖直方向上距离最远的点之间的格子数,所以我们可以先对 rr 数组进行排序。

    当第 ii 点从最上面移动到最下面,因为我们不可能真的修改每一个点的位置,它的位置我们不妨认为是 ri+hr_i + h,我们可以令 ri+k=ri+hr_{i + k} = r_i + h,就做到了断环成链,这时的 rr 数组显然是升序的。于是 i[1,k]\forall i \in [1,k],当最上面的点为 rir_i 时,都可以用 rir_iri+k1r_{i + k - 1} 表示。

    我们发现在平移的过程中,只有当有图像向上移动到最下面一行的对应单元格中时,即最上面的点改变时,xx 的值才可能改变。

    记当前最上面的点为 iii[1,k]i \in [1,k],此时竖直方向上距离最远的点之间的格子数为 res=ri+k1ri+1res = r_{i + k - 1} - r_i + 1 (包括端点,所以加一),分以下情况讨论:

    • x<resx < res,直接跳过。

    • x=resx = res,就有可能更新 sumxsumx 的值,而想要用尽可能少的步骤使第 ii 个点为最上面的点,要么是前 i1i - 1 个点向上移动 ri1r_{i - 1},要么是第 ii 个点向下平移 hri+1h - r_i + 1(向下移动 hrih - r_i 是到矩形的最下端,还要加一才能到最上端)。

      sumx=min{sumx,ri1,hri+1}sumx = \min \{ sumx, r_{i - 1}, h - r_i + 1 \}

    • x>resx > res,令 x=resx = ressumx=min{ri1,hri+1}sumx = \min \{ r_{i - 1}, h - r_i + 1 \}

    另一种情况同理。

    细节

    • 十年 OI 一场空,不开 long long 见祖宗。

    • 注意初始化。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=1e5+10;
    long long h,w,k;
    long long r[N*2],c[N*2];
    long long x=1e18,y=1e18,sumx=1e18,sumy=1e18;
    
    int main(){
    	scanf("%lld%lld%lld",&h,&w,&k);
    	for(int i=1;i<=k;i++){
    		scanf("%lld%lld",&r[i],&c[i]);
    		r[i+k]=r[i]+h;c[i+k]=c[i]+w;
    	}
    	r[0]=0;c[0]=0;
    	sort(r+1,r+1+k*2);
    	sort(c+1,c+1+k*2);
    	for(int i=1;i<=k;i++){
    		long long res=r[i+k-1]-r[i]+1;
    		if(x>=res){
    			if(x==res) sumx=min(min(sumx,r[i-1]),h-r[i]+1);
    			else{
    				x=res;
    				sumx=min(r[i-1],h-r[i]+1);
    			}
    		} 
    	}
    	for(int i=1;i<=k;i++){
    		long long res=c[i+k-1]-c[i]+1;
    		if(y>=res){
    			if(y==res) sumy=min(min(sumy,c[i-1]),w-c[i]+1);
    			else{
    				y=res;
    				sumy=min(c[i-1],w-c[i]+1);
    			}
    		} 
    	}
    	printf("%lld %lld",x*y,sumx+sumy);
    } 
    
    • 1

    信息

    ID
    7335
    时间
    1000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者