2025-10-24 hetao1733837的刷题记录
A.Luogu P7074 [CSP-J 2020] 方格取数
原题链接:https://www.luogu.com.cn/problem/P7074
分析:一眼dp,设dp[i][j]表示走到(i,j)可以获得的最大收益。这题的瓶颈在于不能走重复的路,那么我们就多记录两个数组up[i][j]表示从上或左走到(i,j)的最大收益,down[i][j]表示从下或左走到(i,j)的最大收益。
初始化:
考虑转移:
当时
答案:
注意:当不是同一列时,只能用dp数组转移,这样复合每一列直上直下的定义。
正解:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1005;
int n, m, dp[N][N], up[N][N], down[N][N];
int a[N][N];
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){cin >> a[i][j];}}dp[1][1] = a[1][1];up[1][1] = a[1][1];for (int i = 2; i <= n; i++){up[i][1] = up[i - 1][1] + a[i][1];dp[i][1] = up[i][1];}for (int j = 2; j <= m; j++){for (int i = 1; i <= n; i++){if (i == 1){up[i][j] = dp[i][j - 1] + a[i][j];}else{up[i][j] = max(up[i - 1][j], dp[i][j - 1]) + a[i][j];}}for (int i = n; i >= 1; i--){if (i == n){down[i][j] = dp[i][j - 1] + a[i][j];}else{down[i][j] = max(down[i + 1][j], dp[i][j - 1]) + a[i][j];}}for (int i = 1; i <= n; i++)dp[i][j] = max(up[i][j], down[i][j]);} cout << dp[n][m];
}
这题给了我们一些启示,就是在网格中,我们考虑把行和列分开考虑,把一维的更新混在另一维中,进行我们想要的。
B.Luogu P8818 [CSP-S 2022] 策略游戏
原题链接:P8818 [CSP-S 2022] 策略游戏 - 洛谷
分析:我以为是个很显然的贪心,其实是假的,我拿了两个ST表维护了一下,结果只有40
/(ㄒoㄒ)/~~
好吧,我们做一下修改。
瓶颈在于本题存在负数。
那么,我们就要维护6个ST表,分别表示A数组区间最大值,区间最小值,负数域最大值,非负数域最小值;B数组区间最大值,区间最小值(为啥A开4个,B开2个?因为他善,因为我们先考虑的A,后考虑的B,依据A的决策,可以适当挑选B)。
OK,正解!
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005;
int amx[N][21], amn[N][21], afumx[N][21], a0mn[N][21];
int bmx[N][21], bmn[N][21];
int n, m, q;
int a, b;
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> m >> q;for (int i = 1; i <= n; i++){cin >> a;amx[i][0] = a;amn[i][0] = a;if (a >= 0){a0mn[i][0] = a;afumx[i][0] = 0xc0c0c0c0c0c0c0c0;}else{afumx[i][0] = a; a0mn[i][0] = 0x3f3f3f3f3f3f3f3f;}}for (int i = 1; i <= m; i++){cin >> b;bmx[i][0] = b;bmn[i][0] = b;}for (int j = 1; (1 << j) <= n; j++){for (int i = 1; i + (1 << j) - 1 <= n; i++){int tmp = i + (1 << (j - 1));amx[i][j] = max(amx[i][j - 1], amx[tmp][j - 1]);afumx[i][j] = max(afumx[i][j - 1], afumx[tmp][j - 1]);amn[i][j] = min(amn[i][j - 1], amn[tmp][j - 1]);a0mn[i][j] = min(a0mn[i][j - 1], a0mn[tmp][j - 1]);}}for (int j = 1; (1 << j) <= n; j++){for (int i = 1; i + (1 << j) - 1 <= n; i++){int tmp = i + (1 << (j - 1));bmx[i][j] = max(bmx[i][j - 1], bmx[tmp][j - 1]);bmn[i][j] = min(bmn[i][j - 1], bmn[tmp][j - 1]);}}while (q--){int l1, r1, l2, r2;cin >> l1 >> r1 >> l2 >> r2;int tmp1 = log2(r1 - l1 + 1), tmp2 = log2(r2 - l2 + 1);int k1 = r1 - (1 << tmp1) + 1;int k2 = r2 - (1 << tmp2) + 1;int ans1 = max(amx[l1][tmp1], amx[k1][tmp1]);int ans2 = min(amn[l1][tmp1], amn[k1][tmp1]);int ans3 = max(afumx[l1][tmp1], afumx[k1][tmp1]);int ans4 = min(a0mn[l1][tmp1], a0mn[k1][tmp1]);int ans5 = max(bmx[l2][tmp2], bmx[k2][tmp2]);int ans6 = min(bmn[l2][tmp2], bmn[k2][tmp2]);int ans = 0xc0c0c0c0c0c0c0c0;if (ans1 >= 0){ans = max(ans, ans1 * ans6);}else{ans = max(ans, ans1 * ans5);}if (ans2 >= 0){ans = max(ans, ans2 * ans6);}else{ans = max(ans, ans2 * ans5);}if (ans3 != 0xc0c0c0c0c0c0c0c0){if (ans3 >= 0){ans = max(ans, ans3 * ans6);}else{ans = max(ans, ans3 * ans5);}}if (ans4 != 0x3f3f3f3f3f3f3f3f){if (ans4 >= 0){ans = max(ans, ans4 * ans6);}else{ans = max(ans, ans4 * ans5);}}cout << ans << '\n';}
}
C.Luogu P3865 【模板】ST 表 & RMQ 问题
原题链接:P3865 【模板】ST 表 & RMQ 问题 - 洛谷
突然发现板子没打,紧急补救一下。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int a[N], st[21][N];
int n, m, l, r;
int main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++){cin >> a[i];st[0][i] = a[i];}for (int i = 1; (1 << i) <= n; i++){ for (int j = 1; j + (1 << i) - 1 <= n; j++){ st[i][j] = max(st[i-1][j], st[i-1][j + (1 << (i-1))]);}}for (int i = 1; i <= m; i++){cin >> l >> r;int k = log2(r - l + 1);cout << max(st[k][l], st[k][r - (1 << k) + 1]) << '\n';}return 0;
}