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;
} 
posted @ 2025-08-27 00:09  yabnto  阅读(5)  评论(0)    收藏  举报