刺激的矩阵(exciting)
【题目背景】
丁爷爷是一名长者,他喜欢寻找刺激的东西。
【题目描述】
丁爷爷非常喜欢取最值运算,他认为取最值运算很刺激。
有一天,丁爷爷获得了一个 n × m 的矩阵。他决定在这个矩阵中找乐子。
首先,对于各行,丁爷爷求出了每行内元素的最小值(第 i 行的最小值被存在 ri 中)。同样地,对于各列,丁爷爷又求出了每列内元素的最大值(第i 列的最大值被存在ci 中)。
然后,丁爷爷将所有 ri 取最大值,存放在 R 中;将所有 ci 取最小值,存放在 C 中。这样,刺激的运算就全部做完了。
然而,丁爷爷认为,最终 R 和 C 相等的矩阵才是真正刺激的矩阵。如果最终他发现 R 与 C 不相等,那么他就会十分生气。为了不得罪丁爷爷,他的粉丝 Yazid 不得不把这个矩阵改成一个刺激的矩阵。
而你,需要帮助 Yazid 最小化他修改的次数。也就是说,Yazid 需要修改尽可能少的位置来使这个矩阵变得刺激。
形式化地描述,不妨假设这个矩阵为 An×m。那么:
你需要修改尽可能少的数,使得 R =C。
【输入格式】
从文件 exciting.in 中读入数据。
第一行 3 个整数 n, m, type,分别表示矩阵的行数、列数和数据类型。(数据类型的作用会在下面描述)
接下来 n 行,每行 m 个用空格隔开的整数,描述这个矩阵。其中第 i + 1 行的第 j
个数表示 Ai, j。
【输出格式】
输出到文件 exciting.out 中。
输出一行一个整数,表示需要修改的最少的数的个数。
【样例 1 输入】
3 3 2
10 20 30
20 10 30
10 5 35
【样例 1 输出】
1
【样例 2 输入】
3 3 1
1 2 1
2 1 0
3 3 4
【样例 2 输出】
0
【样例 3 输入】
4 4 0
1 1 3 4
5 1 1 8
9 10 1 1
1 14 15 1
【样例 3 输出】
2
【样例 4】
见选手目录下的 exciting/exciting4.in与 exciting/exciting4.ans。
【样例 5】
见选手目录下的 exciting/exciting5.in与 exciting/exciting5.ans。
【样例 6】
见选手目录下的 exciting/exciting6.in与 exciting/exciting6.ans。
【提示】
样例 1 解释:Yazid 可以把第 1 行第 2 个元素修改为 7,这样这个矩阵就是刺激的了。
【子任务】
对于8% 的数据,保证 n,m ≤ 3,且type = 1。对于另外8% 的数据,有 type= 2。
对于另外 4%的数据,有 n, m ≤5。对于另外 12% 的数据,保证 n ≤10。对于 44% 的数据,保证n, m ≤35。对于 56% 的数据,保证 n, m ≤60。对于 64% 的数据,保证n, m ≤100。对于 72% 的数据,保证 n, m ≤300。对于 88% 的数据,保证n, m ≤1, 000。对于92% 的数据,保证 n, m ≤1, 500。
对于100% 的数据,保证 1 ≤ n, m ≤2, 000,0 ≤ Ai,j ≤ 3 × 106。对于没有说明 type 取值的数据类型,都有type= 0。
对于 type = 1 的数据,保证存在一种最优的修改方案,使得最终得到的刺激矩阵的每个元素都是不超过 5 的非负整数。
对于 type = 2 的数据,保证答案不超过 1。
题解:我们可以发现R与C所代表的点是相等的。将所有数据进行排序,先从小到大存入,在列上减去对应的数,再从大到小存入,在行上减去对应的数。将两者相加求最小值就是答案。
Code:
var
ans,f,x,y,b:array[0..4000005] of longint;
a:array[0..2005,0..2005] of longint;
n,m,t,i,j,sum,cnt,minans,min,l,r:longint;
procedure sort(l,r:longint);
var i,j,v,t:longint;
begin
i:=l;j:=r;v:=f[random(r-l+1)+l];
repeat
while f[i]<v do inc(i);
while f[j]>v do dec(j);
if not(i>j) then
begin
t:=f[i];f[i]:=f[j];f[j]:=t;
t:=x[i];x[i]:=x[j];x[j]:=t;
t:=y[i];y[i]:=y[j];y[j]:=t;
inc(i);dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
begin
assign(input,'exciting.in');reset(input);
assign(output,'exciting.out');rewrite(output);
randomize;
readln(n,m,t);
for i:=1 to n do
for j:=1 to m do
begin
read(a[i,j]);
inc(sum);
f[sum]:=a[i,j];
x[sum]:=i;
y[sum]:=j;
end;
sort(1,sum);
for i:=1 to m do b[i]:=n;
min:=n;
for i:=1 to sum do
begin
dec(b[y[i]]);
if b[y[i]]<min then min:=b[y[i]];
if (f[i]<>f[i+1])or(i=sum) then
begin
inc(cnt);
ans[cnt]:=min;
end;
end;
for i:=1 to n do b[i]:=m;
min:=m;minans:=maxlongint;
inc(cnt);
for i:=sum downto 1 do
begin
dec(b[x[i]]);
if b[x[i]]<min then min:=b[x[i]];
if (f[i]<>f[i-1])or(i=1) then
begin
dec(cnt);
ans[cnt]:=ans[cnt]+min;
if ans[cnt]<minans then minans:=ans[cnt];
end;
end;
writeln(minans);
close(input);close(output);
end.