Codeforces Round #545 (Div. 2) C. Skyscrapers

题解

题目大意,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;
}

猜你喜欢

转载自blog.csdn.net/CaprYang/article/details/88570369