发布于 

Skycsrapers

Skycsrapers

CF 1137 A

这是我的第一场Div.1,结果打完之后又掉回Div.2了,结束了我短暂的Div.1生涯。。。

题目来源:Codeforces

分析

题目给出了一个\(n \times m\)的地图mp[][],假设其由n条横向道路和m条纵向道路组成,并且在每一个路口都有一个摩天大楼,高度为mp[i][j]。然后,我们希望在不更改同一行或同一列的大楼之间的高度关系的情况下,令高度最高的大楼的高度尽可能的小。

这其实就是一个Hash,我们对于每一行或者每一列都Hash映射到尽可能小的数即可。不过我们还要考虑一个点同时对行和列的影响。譬如一个点在行中算出其为10,但是在列中是最小的。所以我们需要令列中的所有数都按照正常Hash的情况再加9。所以实际上,我们可以记录,每个点在行中或者列中,小于等于它的数的Hash值的数目和大于等于的数目,即smaller[i][j][]bigger[i][j][]。第三维通过0,1来记录行列,然后答案在smaller[i][j][]bigger[i][j][]中取组合的最大值即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <iostream>
#include <algorithm>
#include <string>

#define MAXN 1010

using namespace std;

struct A
{
int i, j;
int x;

A(){}

A(int x, int i, int j):x(x), i(i), j(j) {}

const bool operator < (const A &tmp) const
{
return this->x < tmp.x;
}

const bool operator != (const A &tmp) const
{
return this->x != tmp.x;
}

}a[MAXN];

int mp[MAXN][MAXN];
int smaller[MAXN][MAXN][2], bigger[MAXN][MAXN][2];

int main()
{
ios::sync_with_stdio(false);

int n, m;
cin >> n >> m;

for (int i = 1; i<=n; i++)
for (int j = 1; j<=m; j++)
cin >> mp[i][j];

for (int i = 1; i<=n; i++)
{
for (int j = 1; j<=m; j++)
a[j] = A(mp[i][j], i, j);

sort(a+1, a+1+m);

int t = 1;
smaller[ a[1].i ][ a[1].j ][0] = 1;
for (int j = 2; j<=m; j++)
{
if (a[j]!=a[j-1])
t++;

smaller[ a[j].i ][ a[j].j ][0] = t;
}

for (int j = 1; j<=m; j++)
bigger[ a[j].i ][ a[j].j ][0] = t - smaller[ a[j].i ][ a[j].j ][0];
}

for (int j = 1; j<=m; j++)
{
for (int i = 1; i<=n; i++)
a[i] = A(mp[i][j], i, j);

sort(a+1, a+1+n);

int t = 1;
smaller[ a[1].i ][ a[1].j ][1] = 1;
for (int i = 2; i<=n; i++)
{
if (a[i]!=a[i-1])
t++;

smaller[ a[i].i ][ a[i].j ][1] = t;
}

for (int i = 1; i<=n; i++)
bigger[ a[i].i ][ a[i].j ][1] = t - smaller[ a[i].i ][ a[i].j ][1];
}

for (int i = 1; i<=n; i++)
{
for (int j = 1; j<=m; j++)
{
int ans = max(smaller[i][j][0] + bigger[i][j][1], smaller[i][j][1] + bigger[i][j][0]);
ans = max(ans, smaller[i][j][0] + bigger[i][j][0]);
ans = max(ans, smaller[i][j][1] + bigger[i][j][1]);

cout << ans << " ";
}
cout << endl;
}
}

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 [@Songer](https://blog.songer.xyz/) 创建,使用 Stellar 作为主题。