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