ABC 224 | E - Integers on Grid
题目描述
给定一个\(H \times W\)的矩阵,给定\(N\)个三元组\((r_i, w_i, a_i)\),表示\((r_i, w_i)\)位置的值为\(a_i\),其余格子上数值为\(0\)。
\(Takahashi\)将分别以\((r_i, w_i)\)作为起始位置,从当前位置走到同行或者同列且数值大于当前位置的格子处,输出从\((r_i, w_i)\)出发最多能走几步?
数据范围
- \(2 \le H, W \le 2 \times 10^5\)
- \(1 \le N \le \min(2 \times 10^5, HW)\)
- \(1 \le r_i \le H, 1 \le c_i \le W\)
- \(1 \le a_i \le 10^9\)
解题思路
使用动态规划算法解决问题。
- 状态表示
\(dp[i]:\)从\((r_i, c_i)\)出发能够走的最大步数
由于除给出的\((r_i, c_i)\)位置,其余位置都是\(0\),所以只需对给出的\(n\)个位置进行状态表示,因为从\((r_i, c_i)\)只能转移到某个\((r_j, c_j)\)上
-
状态转移
- 由于只能转移到数值更大的位置,所以为保证可以进行状态转移,需要对\(n\)个位置的数值进行降序遍历,同时为避免数值相等导致错误转移,需要将数值相等的位置全部进行状态转移,然后统一进行数组更新。
- 由于只能转移到同行或者同列的位置,所以需要找出当前位置所在行\(r_i\)以及所在列\(c_i\)最大的\(dp\)值,将该值记为\(rmax[r_i], cmax[c_i]\),在每轮状态转移后进行数组更新。
-
语法问题
map默认从小到大进行排序,该题需要进行倒序遍历
for(auto t = mp.rbegin(); t != mp.rend(); t ++){ //对map进行降序遍历 for(auto i : t -> second) f[i] = max(rmax[r[i]], cmax[c[i]]); //t是迭代器,只能使用'->' for(auto i : t -> second) { rmax[r[i]] = max(f[i] + 1, rmax[r[i]]); cmax[c[i]] = max(f[i] + 1, cmax[c[i]]); } }
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
const int N = 2e5 + 10;
int h, w, n;
int r[N], c[N], a[N];
int rmax[N], cmax[N];
int f[N];
map<int, vector<int>> mp;
int main()
{
scanf("%d%d%d", &h, &w, &n);
for(int i = 1; i <= n; i ++){
scanf("%d%d%d", &r[i], &c[i], &a[i]);
mp[a[i]].push_back(i);
}
for(auto t = mp.rbegin(); t != mp.rend(); t ++){
for(auto i : t -> second) f[i] = max(rmax[r[i]], cmax[c[i]]);
for(auto i : t -> second) {
rmax[r[i]] = max(f[i] + 1, rmax[r[i]]);
cmax[c[i]] = max(f[i] + 1, cmax[c[i]]);
}
}
for(int i = 1; i <= n; i ++) printf("%d\n", f[i]);
return 0;
}

浙公网安备 33010602011771号