25-暑期-来追梦noip-卷11
芒果大酬宾
我们考虑对于一个已经成立的集合,加一个点需要满足什么条件,我们不难想到,如果我选的值是集中最大值的倍数,那么这个值就是合法的因为,最大值是其他的倍数,那么最大值的倍数,肯定是其他值的倍数
#include <iostream>
#include <algorithm>
#include <map>
#include <unordered_map>
using namespace std;
const int MaxN = 2e5 + 10;
int f[MaxN], a[MaxN], b[MaxN], n, ans, tot;
unordered_map<int, int> st, cnt;
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i], cnt[a[i]]++;
}
sort(a + 1, a + n + 1, greater<int>());
n = unique(a + 1, a + n + 1) - a - 1;
for (int i = 1; i <= n; i++) {
f[i] = cnt[a[i]];
for (int j = a[i] * 2; j <= a[1]; j += a[i]) {
if (st.count(j))
f[i] = max(f[st[j]] + cnt[a[i]], f[i]);
}
ans = max(ans, f[i]), st[a[i]] = i;
}
cout << ans << '\n';
return 0;
}
删除剩余
考虑部份分,对于第一个暴力搜索,对于第二个,由于 k = 1 说明只有一种可能,答案为 1,对于第三个由于 si 不同可以直接组合数
考虑正解,fij 表示选到 i,删了 j 个,我们考虑什么时候会算重,我们设 pre_x 为上一个 x(下标为 i) 的出现位置,那么删掉 pre_x 到 i - 1 或 pre_x + 1 到 i 其实是一样的,因为 pre_x == x,那么在这里,pre_x + 1 到 i - 1 之间是必须删掉的,只有一种方案,对于pre_x - 1 以及之前的,可以直接缩小范围用过去的 dp 做,然后由于是两种情况相同,所以需要删掉一个
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#define int long long
using namespace std;
const int MaxN = 1e5 + 10, mod = 1e9 + 7;
int g[MaxN], a[MaxN], pre[MaxN], n, m, k, ans;
map<int, int> f[MaxN];
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
while (cin >> n >> m >> k) {
for (int i = 1; i <= n; i++) {
map<int, int>().swap(f[i]);
cin >> a[i], pre[a[i]] = 0;
f[i][0] = f[i][i] = 1;
}
f[0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
f[i][j] = (f[i - 1][j - 1] + f[i - 1][j]) % mod;
int pos = pre[a[i]];
if (i - pos <= j && pos - 1 >= 0) {
f[i][j] = (f[i][j] - f[pos - 1][j - (i - pos)] + mod) % mod;
}
}
pre[a[i]] = i;
}
cout << f[n][m] << '\n';
}
return 0;
}
芒果的收获季
考虑离散化,那么只有 600 个点
考虑一个 d 会处理一些区间,而不被处理的区间可以交给其它的 d 去处理,所以我们可以写出一个暴力,然后就可以用区间 dp 优化过程。
考虑继续优化,对于 d 其实可能会出现乱序选取,所以我们考虑如何按顺序处理,由于选择的 d 必须要包括此时的最大的 d 所以我们考虑选择 d 最大的区间
#include <iostream>
#include <algorithm>
#include <map>
#define int long long
using namespace std;
const int MaxN = 1e3 + 10;
struct S {
int l, r, d;
} a[MaxN];
int f[MaxN][MaxN], n, cnt, t;
map<int, int> st;
signed main() {
for (cin >> t; t; t--) {
cin >> n, cnt = 0;
map<int, int>().swap(st);
for (int i = 1; i <= n; i++) {
cin >> a[i].l >> a[i].r >> a[i].d;
st[a[i].l] = st[a[i].r] = 0;
}
for (auto &i : st) {
i.second = ++cnt;
}
for (int i = 1; i <= cnt; i++) for (int j = 1; j <= cnt; j++) f[i][j] = 0;
for (int i = 1; i <= n; i++) {
a[i].l = st[a[i].l], a[i].r = st[a[i].r];
}
for (int len = 1; len <= cnt; len++) {
for (int i = 1, j = i + len - 1; j <= cnt; i++, j++) {
int maxd = 0, pos = -1;
for (int k = 1; k <= n; k++) {
if (i <= a[k].l && a[k].r <= j && a[k].d > maxd) {
maxd = a[k].d, pos = k;
}
}
if (pos == -1) continue;
f[i][j] = 1e18;
for (int p = a[pos].l; p <= a[pos].r; p++) {
f[i][j] = min(f[i][j], f[i][p - 1] + f[p + 1][j] + maxd);
}
}
}
cout << f[1][cnt] << '\n';
}
return 0;
}

浙公网安备 33010602011771号