题解
题目大意,n*m矩阵每个位置作为一个独立的询问,问将当前行和列的数值拼在一起离散化为1~x的数值,要求x最小,最后输出每个位置的x。
如果对着每个位置将行列数据加入vector后离散化复杂度O(nm(n+m))过高。
每个位置预处理4个信息,当前位置的值v在当前列的离散化结果中,有lc个比v小的,有gc个比v大的。当前位置的值v在当前行的离散化结果中,有lr个比v小的,有gr个比v大的。
每次将整行数据加入vector离散化后,可以二分得到当前行的所有位置的gl、gr信息,总复杂度O(n*mlogm)。列类似操作。
则每个位置x在当前行和列的离散化结果中的排名为max(lr[x], lc[x]) + max(gr[x], gc[x]) + 1。
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
#define fst first
#define sed second
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e3 + 10;
int g[N][N];
int lc[N][N], gc[N][N], lr[N][N], gr[N][N]; //列/行比当前小/大的数量
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
scanf("%d", &g[i][j]);
for (int i = 1; i <= n; ++i) //行
{
vector<int> vec;
for (int j = 1; j <= m; ++j)
vec.push_back(g[i][j]);
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
for (int j = 1; j <= m; ++j)
{
lc[i][j] = lower_bound(vec.begin(), vec.end(), g[i][j]) - vec.begin(); //小的数量
gc[i][j] = vec.size() - lc[i][j] - 1; //大的数量
}
}
for (int j = 1; j <= m; ++j) //列
{
vector<int> vec;
for (int i = 1; i <= n; ++i)
vec.push_back(g[i][j]);
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
for (int i = 1; i <= n; ++i)
{
lr[i][j] = lower_bound(vec.begin(), vec.end(), g[i][j]) - vec.begin();
gr[i][j] = vec.size() - lr[i][j] - 1;
}
}
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
printf("%d ", max(lc[i][j], lr[i][j]) + max(gc[i][j], gr[i][j]) + 1); //比当前小+比当前大+1行列取max
cout << endl;
}
return 0;
}