AT_agc061_d [AGC061D] Almost Multiplication Table题解

非常好的构造题!山东省集被出了。

应该通俗易懂吧......

思路

考虑二分答案 m i d mid mid,设 L i , j = a i , j − m i d L_{i,j}=a_{i,j}-mid Li,j=ai,j−mid, R i , j = a i , j + m i d R_{i,j}=a_{i,j}+mid Ri,j=ai,j+mid,则 X i Y j ∈ [ L i , j , R i , j ] X_iY_j\in [L_{i,j},R_{i,j}] XiYj∈[Li,j,Ri,j]。我们只需要判断是否有符合条件的构造即可。

不妨设 X n ≤ Y m X_n\le Y_m Xn≤Ym( X n ≥ Y m X_n\ge Y_m Xn≥Ym 同理)埋下伏笔,设 S i S_i Si 为目前 X i X_i Xi 的最小值(初始为 1 1 1), D i D_i Di 为目前 Y i Y_i Yi 的最大值,初始为 2 × 10 9 2\times 10^9 2×109。考虑逼近法,逐渐逼近 X i X_i Xi 与 Y i Y_i Yi 的真实值。

我们考虑依次进行以下操作:

  1. 从前往后枚举 S i S_i Si,若 S i ≤ S i − 1 S_i\le S_{i-1} Si≤Si−1,则 S i ⟵ S i − 1 + 1 S_i\longleftarrow S_{i-1}+1 Si⟵Si−1+1。同时枚举 D j D_j Dj,若 S i D j < L i , j S_iD_j< L_{i,j} SiDj<Li,j,由于 D j D_j Dj 已经是 Y j Y_j Yj 的最大值了,所以只能令 S i ⟵ ⌈ L i , j D j ⌉ S_i \longleftarrow \left \lceil \frac{L_{i,j}}{D_j} \right \rceil Si⟵⌈DjLi,j⌉。
  2. 从后往前枚举 D i D_i Di,若 D i ≥ D i + 1 D_i\ge D_{i+1} Di≥Di+1,则 D i ⟵ D i + 1 − 1 D_i\longleftarrow D_{i+1}-1 Di⟵Di+1−1。同时枚举 S j S_j Sj,若 S j D i > R j , i S_jD_i> R{j,i} SjDi>Rj,i,由于 S j S_j Sj 已经是 X j X_j Xj 的最小值了,所以只能令 D i ⟵ ⌊ L j , i S j ⌋ D_i\longleftarrow \left \lfloor \frac{L_{j,i}}{S_j} \right \rfloor Di⟵⌊SjLj,i⌋。
  3. 若 S i S_i Si 与 D j D_j Dj 均符合题意,则 S i S_i Si 与 D j D_j Dj 是 X i X_i Xi 与 Y j Y_j Yj 的一组合法构造。
  4. 若 X n > Y m X_n>Y_m Xn>Ym 或 Y m ≤ 0 Y_m\le 0 Ym≤0,则直接返回不合法。

按照上述顺序依次操作构造出的序列显然是对的。下面我们证明一下操作的复杂度:

  1. 显然,每一轮操作中,至少存在一个 S i S_i Si 变大或 D j D_j Dj 变小。
  2. 显然,如果我们想让惩罚值最小, X i Y j X_iY_j XiYj 不能超过 10 9 10^9 109(否则我还不如直接给 X X X 赋值为 1 , 2 , ... , n 1,2,\dots ,n 1,2,...,n,将 Y Y Y 赋值为 1 , 2 , ... , m 1,2,\dots ,m 1,2,...,m)。
  3. 还记得前面说的吗?要求 X n ≤ Y m X_n\le Y_m Xn≤Ym,又由于 X i Y j ≤ 10 9 X_iY_j\le 10^9 XiYj≤109,所以 X i ≤ 10 9 ≈ 3 × 10 4 ≤ Y j X_i\le \sqrt{10^9}\approx 3\times 10^4 \le Y_j Xi≤109 ≈3×104≤Yj。则每个 X i X_i Xi 最多增加 3 × 10 4 3\times 10^4 3×104 次,每个 Y j Y_j Yj 最多减少 3 × 10 4 3\times 10^4 3×104 次。故总轮数不会超过 3 × 10 4 ( n + m ) ≈ 3 × 10 5 3\times 10^4(n+m)\approx 3\times 10^5 3×104(n+m)≈3×105。

证明完毕。

加上外面的二分与具体实现,总时间复杂度为 O ( ( n + m ) n m V log ⁡ V ) O((n+m)nm\sqrt{V} \log_{}{V} ) O((n+m)nmV logV),其中 V = 2 × 10 9 V=2\times 10^9 V=2×109。(算下来不到 10 7 10^7 107)

代码

注意数组的第一维与第二维不要写反,不然调起来可能比较麻烦。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
long long n,m,a[10][10],l[10][10],r[10][10];
long long s[10],d[10];
bool check(long long x)
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++) l[i][j]=max(1ll,a[i][j]-x),r[i][j]=a[i][j]+x;
	for(int i=1;i<=n;i++) s[i]=1;
	for(int i=1;i<=m;i++) d[i]=2e9;
	bool op=0;
	while(1)
	{
		bool flag=0;
		for(int i=1;i<=n;i++)
		{
			if(i-1&&s[i]<=s[i-1]) flag=1,s[i]=s[i-1]+1;
			for(int j=1;j<=m;j++)
				if(s[i]*d[j]<l[i][j]) flag=1,s[i]=(l[i][j]+d[j]-1)/d[j];	
		}
		for(int i=m;i>=1;i--)
		{
			if(i+1<=m&&d[i]>=d[i+1]) flag=1,d[i]=d[i+1]-1;
			for(int j=1;j<=n;j++)
				if(s[j]*d[i]>r[j][i]) flag=1,d[i]=r[j][i]/s[j];
		}
		if(s[n]>d[m]||d[1]<=0) op=1;
		if(op||!flag) break;
	}
	if(!op) return 1;
	op=0;
	for(int i=1;i<=n;i++) s[i]=2e9;
	for(int i=1;i<=m;i++) d[i]=1;
	while(1)
	{
		bool flag=0;
		for(int i=1;i<=m;i++)
		{
			if(i-1&&d[i]<=d[i-1]) flag=1,d[i]=d[i-1]+1;
			for(int j=1;j<=n;j++)
				if(d[i]*s[j]<l[j][i]) flag=1,d[i]=(l[j][i]+s[j]-1)/s[j];	
		}
		for(int i=n;i>=1;i--)
		{
			if(i+1<=n&&s[i]>=s[i+1]) flag=1,s[i]=s[i+1]-1;
			for(int j=1;j<=m;j++)
				if(s[i]*d[j]>r[i][j]) flag=1,s[i]=r[i][j]/d[j];
		}
		if(d[m]>s[n]||s[1]<=0) op=1;
		if(op||!flag) break;
	}
	if(!op) return 1;
	return 0;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++) cin>>a[i][j];
	long long l=0,r=2000000000,ans=-1;
	while(l<=r)
	{
		long long mid=(l+r)>>1ll;
		if(check(mid)) r=mid-1,ans=mid;
		else l=mid+1;
	}
	cout<<ans<<"\n";
	check(ans);
	for(int i=1;i<=n;i++) cout<<s[i]<<" ";
	cout<<"\n";
	for(int i=1;i<=m;i++) cout<<d[i]<<" ";
    return 0;
}
相关推荐
故事和你917 小时前
洛谷-算法2-4-字符串2
开发语言·数据结构·c++·算法·深度优先·动态规划·图论
cpp_25017 小时前
P3374 【模板】树状数组 1
数据结构·c++·算法·题解·洛谷·树状数组
郝学胜-神的一滴7 小时前
干货版《算法导论》 02 :算法效率核心解密
java·开发语言·数据结构·c++·python·算法
WL_Aurora7 小时前
Python 算法基础篇之回溯
python·算法
智者知已应修善业7 小时前
【51单片机控制的交通信号灯三按键切换调节时分秒加减】2023-8-26
c++·经验分享·笔记·算法·51单片机
MicroTech20257 小时前
量子退火赋能:微算法科技(NASDAQ: MLGO)图像分割算法开启未来科技新视界
科技·算法·量子计算
枕星而眠7 小时前
C语言数组专题:从一维到二维,吃透内存与指针
java·数据结构·算法
zmzb01037 小时前
C++课后习题训练记录Day120
开发语言·c++
ximu_polaris7 小时前
设计模式(C++)-行为型模式-状态模式
c++·设计模式·状态模式