http://rank.pintia.cn/basic.html
rk343
今天还是打得比较开心的
A
我们采用了二分+线段树,先在[i%k,k-1]里找最左的符合题意的点(完成时间小于当前时间),如果没找到,再在[0,i%k-1]里找,还没找到就忽略此任务
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 7; ll tree[N << 2]; int n; #define ls (p << 1) #define rs (p << 1 | 1) #define lson ls, l, mid #define rson rs, mid + 1, r void update(int x, ll num, int p = 1, int l = 1, int r = n) { // a[x] = num if (l == r) { if (l == x) tree[p] = num; return; } int mid = (l + r) / 2; if (x <= mid) update(x, num, lson); else update(x, num, rson); tree[p] = min(tree[ls], tree[rs]); } ll query(int x, int y, int p = 1, int l = 1, int r = n) { // [x,y]'s min val if (x <= l && r <= y) return tree[p]; int mid = (l + r) / 2; if (y <= mid) return query(x, y, lson); if (x > mid) return query(x, y, rson); return min(query(x, mid, lson), query(mid + 1, y, rson)); } int cnt[N]; void chk(int id, ll now, ll len) { int L = id + 1, R = id; int l = L, r = n; // fit segment tree int mid; int ans = -1; while (l <= r) { mid = l + r >> 1; if (query(L, mid) <= now) { ans = mid, r = mid - 1; } else l = mid + 1; } if (ans == -1) { l = 1, r = R; while (l <= r) { // 找最左的右边界 mid = l + r >> 1; if (query(1, mid) <= now) { ans = mid, r = mid - 1; } else l = mid + 1; } } if (ans != -1) { cnt[ans - 1] += 1; update(ans, now + len); } } signed main() { int m; ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); cin >> n >> m; ll arriveTime, processTime; for (int i = 0; i < m; ++i) { cin >> arriveTime >> processTime; chk(i % n, arriveTime, processTime); } int maxVal = 0, lastid; for (int i = 0; i < n; ++i) maxVal = max(maxVal, cnt[i]); vector<int> res; for (int i = 0; i < n; ++i) if (cnt[i] == maxVal) res.emplace_back(i); for (int i = 0; i < res.size(); ++i) { cout << res[i]; if (i != res.size() - 1) cout << ' '; } return 0; }
B
最后改好了没有交上,就用凸包搞一下然后逆着输出即可
// debug ing
D
题意:有一个乱七八糟的图,要你删到最小生成树,问删掉的总边权和。表示从
到
节点生成一个
的完全图。
思路:用set维护区间左端点,即可模拟线段覆盖。如果最后覆盖成了一个连通块即可联通。
#include <bits/stdc++.h> typedef long long ll; #define int ll #define rep(i, l, r) for (int i = l; i <= r; ++i) using namespace std; const int N = 1e5 + 7; struct nod { int l, r, w; bool operator<(const nod o) const { return w < o.w; } } t; inline ll sum(ll l, ll r) { ll n = r - l + 1; return (n - 1) * n / 2; } void solve() { int n, m; cin >> n >> m; vector<nod> edg; rep(i, 1, m) { cin >> t.l >> t.r >> t.w; edg.emplace_back(t); } int ans = 0; sort(edg.begin(), edg.end()); set<int> s; rep(i, 1, n) s.insert(i); rep(i, 0, m - 1) { vector<set<ll>::iterator> vi; int cnt = 0, st = edg[i].l, ed = edg[i].r; auto l = s.upper_bound(st); auto r = s.upper_bound(ed); for (auto it = l; it != r; ++it) { auto now = it; vi.push_back(it); cnt++; } for (auto ii : vi) s.erase(ii); ans += (sum(st, ed) - cnt) * edg[i].w; } if (s.size() == 1) cout << ans; else cout << "Gotta prepare a lesson"; } signed main() { int T; ios::sync_with_stdio(0), cin.tie(0); cin >> T; rep(i, 1, T) { cout << "Case #" << i << ": "; solve(); if (i != T) cout << '\n'; } return 0; }
F
- 如果A点在圈里(
)直接走到B的圈里就行了。
- 否则先走到A圈的最低点,然后再和B圆心连线,走到B圈上即可
H
傻*题。
题意:给定n个点的坐标,这些点构成了一些线段和三角形。问你一个点,要你输出这个点的所有邻点和所有所在的元素编号。
我们用了unordered_map<int,set<int>>
模拟
I
python模拟,PE了一发
K
这个也是阅读理解+模拟题,从起点开始顺着走就可以了,采用vector<vector<int>>
存图,注意特判一下不要越界,越界判定丢包