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;
}