[CF1453C] Triangles - 构造
Description
给一个矩阵,每个元素都是 1−9,对每个 d,选三点都是 d 的,问组成最大的三角形面积多大,每个 d ,都可以把一个数字改成 d,然后算完在改回去。
Solution
一开始读错题了,以为不能把 d 改成 d,也不知道怎么就在 allowed 前面脑补了一个 not,然后大脑炸胡……,跳去切 D 了
这种带构造性质的东西,我们的想法是去提供一个不会比最优解更劣,同时又比较简便的方案
我们钦定底是和坐标轴平行的,那么高也是平行的
假设现在随便选了一个点 A 做底的一个顶点,找一个点 B 做高的顶点,然后我们去修改另一个 C 做底的另一个顶点
这样处理起来比较简单,我们只需要记录每种颜色出现的 i,j 的最大最小值,四种情况,高就很容易算出来,而 AC 的长度是任意的,我们直接把 C 怼到边界上即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
vector<vector<int>> a(n + 2, vector<int>(n + 2));
for (int i = 1; i <= n; i++)
{
string str;
cin >> str;
for (int j = 1; j <= n; j++)
a[i][j] = str[j - 1] - '0';
}
vector<int> imax(11, -1), jmax(11, -1), imin(11, n + 1), jmin(11, n + 1);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
imax[a[i][j]] = max(imax[a[i][j]], i);
imin[a[i][j]] = min(imin[a[i][j]], i);
jmax[a[i][j]] = max(jmax[a[i][j]], j);
jmin[a[i][j]] = min(jmin[a[i][j]], j);
}
}
vector<int> ans(11);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (imin[a[i][j]] <= n)
ans[a[i][j]] = max(ans[a[i][j]], abs(imin[a[i][j]] - i) * (j - 1));
if (imin[a[i][j]] <= n)
ans[a[i][j]] = max(ans[a[i][j]], abs(imin[a[i][j]] - i) * (n - j));
if (imax[a[i][j]] > 0)
ans[a[i][j]] = max(ans[a[i][j]], abs(imax[a[i][j]] - i) * (j - 1));
if (imax[a[i][j]] > 0)
ans[a[i][j]] = max(ans[a[i][j]], abs(imax[a[i][j]] - i) * (n - j));
if (jmin[a[i][j]] <= n)
ans[a[i][j]] = max(ans[a[i][j]], abs(jmin[a[i][j]] - j) * (i - 1));
if (jmin[a[i][j]] <= n)
ans[a[i][j]] = max(ans[a[i][j]], abs(jmin[a[i][j]] - j) * (n - i));
if (jmax[a[i][j]] > 0)
ans[a[i][j]] = max(ans[a[i][j]], abs(jmax[a[i][j]] - j) * (i - 1));
if (jmax[a[i][j]] > 0)
ans[a[i][j]] = max(ans[a[i][j]], abs(jmax[a[i][j]] - j) * (n - i));
}
}
for (int i = 0; i < 10; i++)
cout << ans[i] << " ";
cout << endl;
}
}