constint N = 1e5+10; typedef pair<int, int> pii; pii ranges[N];
intmain(){ int st, ed, n; cin >> st >> ed >> n; for (int i = 0; i < n; i++) cin >> ranges[i].first >> ranges[i].second; sort(ranges, ranges+n); int cnt = 0; bool success = false; for (int i = 0; i < n; i++) { // 从 i 开始找到能覆盖 st 的最大右端点 int j = i, r = -2e9; while (j < n && ranges[j].first <= st) { r = max(r, ranges[j].second); j++; } if (r < st) { cnt = -1; break; } cnt++; st = r; i = j-1; // 更新后的 st 如果等于 ed 也是可以的 // 这时满足了这个线段被覆盖 if (st >= ed) { success = true; break; } } if (success) cout << cnt; else cout << -1; return0; }
听音乐
小 P 正在听音乐,现在他的播放列表里有 n 首音乐,编号为 1,2,…,n,每个音乐有两个属性 ai,bi。
重复听一首音乐会让小 P 感到厌倦,所以当他第 k 次听到音乐 i 时,他得到的愉悦度为 max(ai−(k−1)bi,0)。
小 P 可以控制播放器,具体的在最开始时播放器正准备播放音乐 1,假设目前正准备播放音乐 i,则每次小 P 可以选择:
constint N = 410; int n, m, tim[N], a[N], b[N], ts; int cnt[5010]; bool st[N];
structPII { int first, second; booloperator<(const PII& p) const { return first < p.first; } };
voidread(int& t){ t = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) t = t*10 + (ch ^ 48), ch = getchar(); }
voidaddbucket(int p){ int real = (p-1)%n+1; if (st[real]) return; st[real] = true; int now = a[p]; int times = 0; while (now > 0 && times < m) { cnt[now]++; times++; now -= b[p]; } }
intmain(){ freopen("music.in", "r", stdin); freopen("music.out", "w", stdout); read(n), read(m); for (int i = 1; i <= n; i++) read(a[i]), a[i+n] = a[i]; for (int i = 1; i <= n; i++) read(b[i]), b[i+n] = b[i];
int ans = 0; for (int l = 1; l <= n+1; l++) { memset(cnt, 0, sizeof cnt); memset(st, 0, sizeof st); for (int j = l; j <= n+1; j++) addbucket(j);
for (int r = n+1; r <= 2*n; r++) { int A = n+1-l, B = r-n-1, times = m - (A + B + min(A, B)); if (times <= 0) continue; addbucket(r); int res = 0; for (int k = 5000; k > 0 && times > 0; k--) { int c = min(times, cnt[k]); res += c * k; times -= c; } ans = max(ans, res); } }
printf("%d\n", ans);
return0; }
[NOIP2004] 合并果子
这里大致抽象一下:有 n 堆果子,每次从这里面任意挑出 2 堆合并,每堆果子的数量不同,合并它们需要的体力等于数量,求合并成 1 堆消耗的最小体力。
intmain(){ int n; cin >> n; priority_queue<int, vector<int>, greater<int>> heap; while (n--) { int a; cin >> a; heap.push(a); } int res = 0; while (heap.size() > 1) { int a = heap.top(); heap.pop(); int b = heap.top(); heap.pop(); res += a+b; heap.push(a+b); } // 最后一堆不需要合并 cout << res << endl; return0; }
[CF638C] Road Improvement
给定一棵有 N 个节点的树,你可以使用两支相邻节点的队伍来修筑它们之间的道路 且 每支队伍一天只能工作一次。问最少需要多少天把所有路修完。输出最短时间和具体方案。
constint N = 50010, M = 100010; int h[N], e[M], ne[M], w[M], idx; int n, m; int cnt, len;
voidadd(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; }
// 返回当前结点出发的没用过的最大边权 intdfs(int u, int fa){ multiset<int> s; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (j == fa) continue; int v = w[i] + dfs(j, u); if (v >= len) cnt++; else s.insert(v); } int maxv = 0; while (s.size()) { auto a = s.begin(); auto b = s.lower_bound(len - *a); if (b == a) b++; if (b == s.end()) { maxv = max(maxv, *a); s.erase(a); } else { cnt++; s.erase(a), s.erase(b); } } return maxv; }
boolcheck(int mid){ len = mid, cnt = 0; dfs(1, -1); return cnt >= m; }
intmain(){ memset(h, -1, sizeof h); scanf("%d%d", &n, &m); int l = 0, r = 0; for (int i = 0; i < n-1; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c), add(b, a, c); r += c; } while (l < r) { int mid = (l + r + 1) >> 1; if (check(mid)) l = mid; else r = mid-1; } printf("%d\n", r); return0; }
[NOIP2012] 国王游戏
恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
vector<int> mul(vector<int>& a, int b){ int t = 0; vector<int> res; for (int i = 0; i < a.size() || t; i++) { if (i < a.size()) t = a[i] * b + t; res.push_back(t % 10); t /= 10; } while (res.size() > 1 && res.back() == 0) res.pop_back(); return res; }
vector<int> div(vector<int>& a, int b){ vector<int> res; int r = 0; for (int i = a.size() - 1; i >= 0; i--) { r = r * 10 + a[i]; res.push_back(r / b); r %= b; } reverse(res.begin(), res.end()); while (res.size() > 1 && res.back() == 0) res.pop_back(); return res; }
vector<int> build(int a){ vector<int> res; for (int t = a; t; t /= 10) { res.push_back(t % 10); } return res; }
boolgreater0(vector<int>& a, vector<int>& b){ if (a.size() > b.size()) returntrue; if (a.size() < b.size()) returnfalse;
for (int i = a.size() - 1; i >= 0; i--) { if (a[i] > b[i]) returntrue; elseif (a[i] < b[i]) returnfalse; } returnfalse; }
intmain(){ scanf("%d", &n); for (int i = 0; i <= n; i++) { scanf("%d%d", &p[i].a, &p[i].b); } sort(p+1, p+1+n);
vector<int> T = build(p[0].a); vector<int> ans = {0}; for (int i = 1; i <= n; i++) { vector<int> cur = div(T, p[i].b); if (greater0(cur, ans)) ans = cur; T = mul(T, p[i].a); } for (int i = ans.size() - 1; i >= 0; i--) printf("%d", ans[i]); puts(""); return0; }