2025.2.28 赛后总结
T1
注意到
Code
#include <bits/stdc++.h>
using namespace std;
const int kMaxN = 1e5 + 5;
int n, a[kMaxN], vis[205];
void S() {
cin >> n;
fill(vis + 1, vis + 201, 0);
for (int i = 1; i <= n; ++i) {
cin >> a[i];
++vis[a[i]];
}
int mx = 0;
for (int w = 2; w <= 200; ++w) {
int cnt = 0;
for (int i = 1; i <= 100; ++i) {
if (w - i >= 1) {
int x = i, y = w - i;
if (x > y) {
continue;
}
if (x == y) {
cnt += (vis[x] >> 1);
} else {
cnt += min(vis[x], vis[y]);
}
}
}
mx = max(mx, cnt);
}
cout << mx << '\n';
return;
}
int main() {
cin.tie(0)->sync_with_stdio(false);
int T;
cin >> T;
for (; T--;) {
S();
}
return 0;
}
T2
发现
Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, m, sum, dp[105][100005], w[105], val[105];
signed main() {
cin.tie(0)->sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
cin >> w[i] >> val[i];
sum += val[i];
}
for(int i = 1; i <= sum; ++i) {
dp[0][i] = 1e18;
}
dp[0][0] = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= sum; ++j) {
dp[i][j] = dp[i - 1][j];
if (j >= val[i]) {
dp[i][j] = min(dp[i][j], dp[i - 1][j - val[i]] + w[i]);
}
}
}
for (int i = sum; i >= 0; --i) {
if (dp[n][i] <= m) {
cout << i;
return 0;
}
}
return 0;
}
T3
这题可以二分,但是直接暴力 check 会超时,所以使用双指针优化即可。
Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int kMaxN = 1e5 + 5;
int n, k, a[kMaxN];
vector<int> e[kMaxN];
int check(int x) {
int sum = (n - x) * x + x * (x - 1) / 2;
for (int i = 1; i <= n; ++i) {
for (int j = 0, l = 0; j < e[i].size(); ++j) {
while (l < e[i].size() && e[i][j] - e[i][l] > x) {
++l;
}
sum -= (j - l);
}
}
return sum;
}
signed main() {
cin.tie(0)->sync_with_stdio(false);
cin >> n >> k;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
e[a[i]].emplace_back(i);
}
if (check(n) < k) {
cout << -1;
return 0;
}
int lt = -1, rt = n + 1;
for (int mid; lt + 1 < rt;) {
mid = lt + rt >> 1;
if (check(mid) < k) {
lt = mid;
} else {
rt = mid;
}
}
int d = lt + 1, cnt = check(lt);
for (int i = 1; i <= n - d; ++i) {
if (a[i] != a[i + d]) {
++cnt;
}
if (cnt == k) {
cout << i << ' ' << i + d;
return 0;
}
}
return 0;
}
T4
考虑 DP,分两种情况,可以选和不能选,如果不能选,直接转移,否则使用堆记录能够选的满足条件的那个,然后再转移,这里可以选是不要从不选的那里转移的。
Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int kMaxN = 1e5 + 5, kInf = 1e18;
int n, m, k, f[kMaxN][205];
struct Node {
int s, t, d, w;
bool operator<(const Node& rhs) const {
if (w == rhs.w) {
return d < rhs.d;
}
return w < rhs.w;
}
} a[kMaxN];
bool cmp(Node x, Node y) {
return x.s < y.s;
}
signed main() {
cin.tie(0)->sync_with_stdio(false);
cin >> n >> m >> k;
for (int i = 1; i <= k; ++i) {
cin >> a[i].s >> a[i].t >> a[i].d >> a[i].w;
}
sort(a + 1, a + k + 1, cmp);
for (int i = 2; i <= n + 1; ++i) {
for (int j = 0; j <= m; ++j) {
f[i][j] = kInf;
}
}
priority_queue<Node> h;
for (int i = 1, j = 1; i <= n; ++i) {
while (j <= k && a[j].s == i) {
h.push(a[j]);
++j;
}
while (!h.empty() && h.top().t < i) {
h.pop();
}
if (h.empty()) {
for (int l = 0; l <= m; ++l) {
f[i + 1][l] = min(f[i + 1][l], f[i][l]);
}
} else {
for (int l = 0; l <= m; ++l) {
f[h.top().d + 1][l] = min(f[h.top().d + 1][l], f[i][l] + h.top().w);
}
for (int l = 0; l < m; ++l) {
f[i + 1][l + 1] = min(f[i + 1][l + 1], f[i][l]);
}
}
}
int mn = kInf;
for (int i = 0; i <= m; ++i) {
mn = min(mn, f[n + 1][i]);
}
cout << mn;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术