A. AcWing 3660. 最短时间
题目链接:https://www.acwing.com/problem/content/3663/
题目大意:求 \(n \times m\) 的矩阵中所有各自到 \((r,c)\) 的最短距离。
解题思路:四角的各自的距离的最大值。
示例程序:
#include <bits/stdc++.h>
using namespace std;
int T, n, m, r, c;
int main() {
cin >> T;
while (T--) {
cin >> n >> m >> r >> c;
cout << max(r-1, n-r) + max(c-1, m-c) << endl;
}
return 0;
}
B. AcWing 3661. 重置数列
题目链接:https://www.acwing.com/problem/content/3664/
题目大意:按照题目要求进行操作,求最少次数。
解题思路:由于 \(1 \le a_i \le 100\),所有可以先 枚举答案,再 贪心 处理。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int T, n, k, a[maxn], ans;
int solve(int x) {
int p = 0, cnt = 0;
while (p < n) {
if (a[p] == x) p++;
else {
p += k;
cnt++;
}
}
return cnt;
}
int main() {
cin >> T;
while (T--) {
cin >> n >> k;
for (int i = 0; i < n; i++) cin >> a[i];
ans = (n - 1) / k + 1;
for (int i = 1; i <= 100; i++)
ans = min(ans, solve(i));
cout << ans << endl;
}
return 0;
}
C. AcWing 3662. 最大上升子序列和
题目链接:https://www.acwing.com/problem/content/3665/
题目大意:求最大上升子序列和。
解题思路:
用 \(f_i\) 表示以 \(a_i\) 结尾(且包含 \(a_i\))的最大上升子序列和,则 \(f_i\) 应该是 \(a_i\) 及所有满足 \(j \lt i\) 且 \(a_j \lt a_i\) 的 \(f_j + a_i\) 的最大值。
但是直接求时间复杂度为 \(O(n^2)\) 会超时,但是可以对 \(a_i\) 做离散化然后用线段树维护这个东西。嗯就是这样。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, a[maxn], p[maxn];
long long tree[maxn<<2];
vector<int> vec;
void push_up(int rt) {
tree[rt] = max(tree[rt<<1], tree[rt<<1|1]);
}
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
long long query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return tree[rt];
long long res = 0;
int mid = (l + r) / 2;
if (L <= mid) res = query(L, R, lson);
if (R > mid) res = max(res, query(L, R, rson));
return res;
}
void update(int p, long long v, int l, int r, int rt) {
if (l == r) {
tree[rt] = max(tree[rt], v);
return;
}
int mid = (l + r) / 2;
if (p <= mid) update(p, v, lson);
else update(p, v, rson);
push_up(rt);
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
vec.push_back(a[i]);
}
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
int m = vec.size();
for (int i = 0; i < n; i++)
p[i] = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin() + 1;
for (int i = 0; i < n; i++) {
int pp = p[i];
if (pp == 1) update(pp, a[i], 1, m, 1);
else {
long long tmp = query(1, pp-1, 1, m, 1) + a[i];
update(pp, tmp, 1, m, 1);
}
}
cout << query(1, m, 1, m, 1) << endl;
return 0;
}