1202 - Investigation
- 最短路徑水題
- Dijkstra
1#include<bits/stdc++.h>
2using namespace std;
3const int mod = 1000000007;
4typedef long long ll;
5typedef pair<ll, int> pii;
6#define pb push_back
7int main () {
8 ios_base::sync_with_stdio(0); cin.tie(0);
9 int n, m; cin >> n >> m;
10 vector<vector<pii>> G(n + 1);
11 for (int i = 0; i < m; i++) {
12 int a, b, c; cin >> a >> b >> c;
13 G[a].pb(pii(c, b));
14 }
15 vector<bool> visit(n + 1);
16 vector<ll> dis(n + 1, ll(m) * ll(1e9));
17 vector<ll> cnt(n + 1, 0), mn(n + 1), mx(n + 1);
18 dis[1] = 0, cnt[1] = 1;
19 priority_queue<pii, vector<pii>, greater<pii>> pq;
20 pq.push(pii(0, 1));
21 while (!pq.empty()) {
22 int u = pq.top().second; pq.pop();
23 if (visit[u]) continue;
24 visit[u] = true;
25 for (pii e : G[u]) {
26 int uu = e.second; ll w = e.first;
27 if (dis[uu] == dis[u] + w) {
28 cnt[uu] = (cnt[u] + cnt[uu]) % mod;
29 mn[uu] = min(mn[uu], mn[u] + 1);
30 mx[uu] = max(mx[uu], mx[u] + 1);
31 } else if (dis[uu] > dis[u] + w) {
32 dis[uu] = dis[u] + w;
33 cnt[uu] = cnt[u] % mod;
34 mn[uu] = mn[u] + 1;
35 mx[uu] = mx[u] + 1;
36 pq.push(pii(dis[uu], uu));
37 }
38 }
39 }
40 cout << dis[n] << " " << cnt[n] << " " << mn[n] << " " << mx[n] << "\n";
41 return 0;
42}
1146 - Counting Bits
問 1 ~ n 的二進制表示法中,共有多少個 1-bit?
十進位 | $$2^2$$ | $$2^1$$ | $$2^0$$ |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 |
2 | 0 | 1 | 0 |
3 | 0 | 1 | 1 |
4 | 1 | 0 | 0 |
5 | 1 | 0 | 1 |
6 | 1 | 1 | 0 |
7 | 1 | 1 | 1 |
觀察 0/1 交替的方式,最末位是每隔 1 個,接下來是每隔 2 個,接下來是每隔 4 個…
1#include<bits/stdc++.h>
2using namespace std;
3typedef long long ll;
4int main() {
5 ll n, ans = 0;
6 cin >> n; n++;
7 for (ll i = 1; i <= n; i <<= 1) {
8 ll c = n / i;
9 if (c & 1) ans += c / 2 * i + n % i;
10 else ans += c / 2 * i;
11 }
12 cout << ans << "\n";
13 return 0;
14}
11677 - Network Breakdown
題目是問給一張圖,每次刪除一條邊後,回答所剩的聯通塊數目。
用 Union Find Tree 維護聯通塊,離線倒著回答詢問,也就是一條一條加回去。
1#include<bits/stdc++.h>
2using namespace std;
3typedef pair<int, int> pii;
4#define x first
5#define y second
6vector<pii> remove(vector<pii> e, vector<pii> q) {
7 sort(q.begin(), q.end());
8 vector<pii> ret;
9 for (pii p : e) {
10 auto iter = lower_bound(q.begin(), q.end(), p);
11 if (iter == q.end() || *iter != p)
12 ret.push_back(p);
13 }
14 return ret;
15}
16struct UF {
17 int cnt;
18 vector<int> p, r;
19 UF(int n): cnt(n) {
20 p.resize(n + 1), r.resize(n + 1);
21 for (int i = 1; i <= n; i++) p[i] = i;
22 }
23 int par(int x) {
24 return p[x] = ((p[x] == x) ? x : par(p[x]));
25 }
26 void uni(int a, int b) {
27 a = par(a), b = par(b);
28 if (a == b) return;
29 if (r[a] < r[b]) {int t = a; a = b; b = t;}
30 p[b] = a, r[a] += (r[a] == r[b]), cnt--;
31 }
32};
33int main() {
34 ios::sync_with_stdio(0); cin.tie(0);
35 int n, m, k; cin >> n >> m >> k;
36 UF T(n);
37 vector<pii> e(m), q(k);
38 for (int i = 0; i < m; i++) {
39 int a, b; cin >> a >> b;
40 e[i] = pii(min(a, b), max(a, b));
41 }
42 for (int i = 0; i < k; i++) {
43 int a, b; cin >> a >> b;
44 q[i] = pii(min(a, b), max(a ,b));
45 }
46 e = remove(e, q);
47 for (pii p : e)
48 T.uni(p.x, p.y);
49 vector<int> ans;
50 reverse(q.begin(), q.end());
51 for (pii p : q) {
52 ans.push_back(T.cnt);
53 T.uni(p.x, p.y);
54 }
55 for(int i = k - 1; i >= 0 ; i--)
56 cout << ans[i] << " ";
57 return 0;
58}
2189 - Point Location Test
基礎的幾何題。
1#include<bits/stdc++.h>
2using namespace std;
3typedef long long ll;
4typedef pair<ll, ll> point;
5#define x first
6#define y second
7ll check(point p[]) {
8 ll dx = p[1].x - p[0].x, dy = p[1].y - p[0].y;
9 return (p[2].y - p[1].y) * dx + (p[1].x - p[2].x) * dy;
10}
11int main () {
12 ios::sync_with_stdio(0), cin.tie(0);
13 int t; cin >> t;
14 while (t--) {
15 point p[3];
16 for (int i = 0; i < 3; i++)
17 cin >> p[i].x >> p[i].y;
18 ll c = check(p);
19 if (c > 0) cout << "LEFT\n";
20 else if (c < 0) cout << "RIGHT\n";
21 else cout << "TOUCH\n";
22 }
23 return 0;
24}
2191 - Polygon Area
給一個簡單多邊形,輸出面積的兩倍。
1#pragma GCC optimization ("O3")
2#include<bits/stdc++.h>
3using namespace std;
4typedef long long ll;
5typedef pair<ll, ll> pii;
6#define x first
7#define y second
8#define pb push_back
9ll det(vector<pii> &p, int n) {
10 ll cnt = 0;
11 for (int i = 0; i < n; i++)
12 cnt += p[i].x * p[i + 1].y - p[i + 1].x * p[i].y;
13 return (cnt > 0) ? cnt : -cnt;
14}
15int main() {
16 ios::sync_with_stdio(0), cin.tie(0);
17 int n; cin >> n;
18 vector<pii> p(n);
19 for (int i = 0; i < n; i++)
20 cin >> p[i].x >> p[i].y;
21 p.pb(p[0]);
22 cout << det(p, n) << "\n";
23 return 0;
24}
2195 - Convex Hull
- 這題是要求在凸包上的所有點,所以
cross() < 0
才需要拔掉。 cross
的部分要記得開 long long,不然會溢位。
1// monotone chain
2#include<bits/stdc++.h>
3using namespace std;
4struct point {
5 long long x, y;
6 point() {}
7 point(long long _x, long long _y) { x = _x, y = _y;}
8 point operator-(const point p) {
9 return point(x - p.x, y - p.y);
10 }
11 long long cross(const point &p) {
12 return x * p.y - y * p.x;
13 }
14};
15static bool cmp(const point &a, const point &b) {
16 return (a.x < b.x) || (a.x == b.x && a.y < b.y);
17}
18void convex_hull(vector<point> p, vector<point> &h) {
19 sort(p.begin(), p.end(), cmp);
20 h.resize(p.size() + 1);
21 int m = 0;
22 for (int i = 0; i < p.size(); i++) {
23 while (m >= 2 &&
24 (h[m - 1] - h[m - 2]).cross(p[i] - h[m - 2]) < 0)
25 m--;
26 h[m++] = p[i];
27 }
28 for (int i = p.size() - 2, t = m + 1; i >= 0; i--) {
29 while (m >= t &&
30 (h[m - 1] - h[m - 2]).cross(p[i] - h[m - 2]) < 0)
31 m--;
32 h[m++] = p[i];
33 }
34 if (p.size() > 1) m--;
35 h.resize(m);
36}
37int main () {
38 ios::sync_with_stdio(0), cin.tie(0);
39 int n; cin >> n;
40 vector<point> P(n);
41 for (int i = 0; i < n; i++)
42 cin >> P[i].x >> P[i].y;
43 vector<point> H;
44 convex_hull(P, H);
45 cout << H.size() << "\n";
46 for (point p : H)
47 cout << p.x << " " << p.y << "\n";
48 return 0;
49}
2205 - Gray Code
1#pragma GCC optimization ("O3")
2#include<bits/stdc++.h>
3using namespace std;
4typedef long long ll;
5typedef pair<int, int> pii;
6int main() {
7 ios::sync_with_stdio(0), cin.tie(0);
8 int n; cin >> n;
9 for (int i = 0; i < (1 << n); i++) {
10 for (int j = n - 1; j >= 0; j--) {
11 int a = i >> j;
12 int b = a >> 1;
13 cout << ((a ^ b) & 1);
14 }
15 cout << '\n';
16 }
17 return 0;
18}
1624 - Chessboard and Queens
1#pragma GCC optimization ("O3")
2#include<bits/stdc++.h>
3using namespace std;
4bool a[8], b[20], c[20];
5char m[8][9];
6int ans = 0;
7void dfs (int i) {
8 if (i == 8) {
9 ans++;
10 return;
11 }
12 for (int j = 0; j < 8; j++) {
13 if (m[i][j] == '*') continue;
14 if (a[j] || b[i + j] || c[i - j + 8]) continue;
15 a[j] = b[i + j] = c[i - j + 8] = true;
16 dfs(i + 1);
17 a[j] = b[i + j] = c[i - j + 8] = false;
18 }
19}
20int main() {
21 ios::sync_with_stdio(0), cin.tie(0);
22 for (int i = 0; i < 8; i++) scanf(" %s", m[i]);
23 dfs(0);
24 printf("%d\n", ans);
25 return 0;
26}
2183. Missing Coin Sum
1#include <bits/stdc++.h>
2using namespace std;
3int main() {
4 ios::sync_with_stdio(0), cin.tie(0);
5 int n;
6 cin >> n;
7 vector<int> v(n);
8 for (int i = 0; i < n; ++i)
9 cin >> v[i];
10 sort(v.begin(), v.end());
11 if (v[0] > 1) {
12 cout << "1\n";
13 return 0;
14 }
15 long long sum = v[0];
16 for (int i = 1; i < n; i++) {
17 if (sum < v[i] - 1) {
18 cout << sum + 1 << "\n";
19 return 0;
20 }
21 sum += v[i];
22 }
23 cout << sum + 1 << "\n";
24 return 0;
25}
2216. Collecting Numbers
1#include <bits/stdc++.h>
2using namespace std;
3int main() {
4 ios::sync_with_stdio(0), cin.tie(0);
5 int n;
6 cin >> n;
7 vector<int> v(n);
8 for (int i = 0; i < n; i++)
9 cin >> v[i];
10 vector<int> pos(n + 1);
11 for (int i = 0; i < n; i++)
12 pos[v[i]] = i;
13 int ans = 1;
14 for (int i = 2; i <= n; i++)
15 if (pos[i - 1] > pos[i])
16 ans++;
17 cout << ans << "\n";
18 return 0;
19}
2217. Collecting Numbers II
1#include <bits/stdc++.h>
2using namespace std;
3int main() {
4 ios::sync_with_stdio(0), cin.tie(0);
5 int n, q;
6 cin >> n >> q;
7 vector<int> v(n);
8 for (int i = 0; i < n; i++)
9 cin >> v[i];
10 vector<int> pos(n + 1);
11 for (int i = 0; i < n; i++)
12 pos[v[i]] = i;
13 int ans = 1;
14 for (int i = 2; i <= n; i++)
15 if (pos[i - 1] > pos[i])
16 ans++;
17 while (q--) {
18 int a, b;
19 cin >> a >> b;
20 a--, b--;
21 int va = v[a];
22 int vb = v[b];
23 swap(v[a], v[b]);
24 set<int> s {max(va, 2), min(va + 1, n), max(vb, 2), min(vb + 1, n)};
25 for (int i : s)
26 if (pos[i - 1] > pos[i])
27 ans--;
28 pos[va] = b, pos[vb] = a;
29 for (int i : s)
30 if (pos[i - 1] > pos[i])
31 ans++;
32 cout << ans << "\n";
33 }
34 return 0;
35}
1753. String Matching
1#include <bits/stdc++.h>
2using namespace std;
3void z_build(string &s, vector<int> &z) {
4 int bst = z[0] = 0;
5 for (int i = 1; s[i]; ++i) {
6 if (z[bst] + bst < i) z[i] = 0;
7 else z[i] = min(z[bst] + bst - i, z[i - bst]);
8 while (s[z[i]] == s[i + z[i]]) ++z[i];
9 if (z[i] + i > z[bst] + bst) bst = i;
10 }
11}
12int z_match(string &s, string &t) {
13 int ans = 0;
14 int lens = s.length(), lent = t.length();
15 vector<int> z(lens + lent + 1);
16 string st = s + "$" + t;
17 z_build(st, z);
18 for (int i = lens + 1; st[i]; ++i)
19 if (z[i] == lens) ++ans;
20 return ans;
21}
22int main() {
23 ios::sync_with_stdio(0), cin.tie(0);
24 string s, p;
25 cin >> s >> p;
26 cout << z_match(p, s) << '\n';
27 return 0;
28}
1680 - Longest Flight Route
- 找點 1 到點 n 的最長路徑。
- 拓樸排序+DP。
1// DP on DAG
2// Topological Sort
3#pragma GCC optimization ("O3")
4#include<bits/stdc++.h>
5using namespace std;
6typedef long long ll;
7typedef pair<int, int> pii;
8#define pb push_back
9
10int main() {
11 ios::sync_with_stdio(0), cin.tie(0);
12 int n, m;
13 cin >> n >> m;
14 vector<vector<int>> G(n + 1);
15 vector<int> par(n + 1);
16 vector<int> deg(n + 1);
17 vector<int> dis(n + 1, -1e9);
18 dis[1] = 0;
19 for (int i = 0; i < m; i++) {
20 int a, b;
21 cin >> a >> b;
22 G[a].pb(b);
23 deg[b]++;
24 }
25 queue<int> q;
26 for (int i = 1; i <= n; i++) {
27 if (!deg[i]) {
28 q.push(i);
29 }
30 }
31 while (!q.empty()) {
32 int u = q.front();
33 q.pop();
34 for (int uu : G[u]) {
35 deg[uu]--;
36 if (!deg[uu]) {
37 q.push(uu);
38 }
39 if (dis[uu] < dis[u] + 1) {
40 dis[uu] = dis[u] + 1;
41 par[uu] = u;
42 }
43 }
44 }
45 if (dis[n] < 0) {
46 cout << "IMPOSSIBLE\n";
47 } else {
48 vector<int> ans;
49 int v = n;
50 while (v) {
51 ans.pb(v);
52 v = par[v];
53 }
54 cout << ans.size() << "\n";
55 for (int i = ans.size() - 1; i >= 0; i--) {
56 cout << ans[i] << " \n"[!i];
57 }
58 }
59 return 0;
60}
1682 - Flight Routes Check
- 判斷圖是不是一個 SCC,若不是找一對 (a, b) 使得 a 走不到 b。
- Tarjan Algorithm。
1#pragma GCC optimization ("O3")
2#include<bits/stdc++.h>
3using namespace std;
4typedef long long ll;
5typedef pair<int, int> pii;
6#define pb push_back
7
8vector<vector<int>> G;
9vector<int> visit;
10vector<int> low;
11vector<int> id;
12vector<bool> inStk;
13stack<int> st;
14int t;
15
16void dfs(int u) {
17 visit[u] = low[u] = ++t;
18 st.push(u);
19 inStk[u] = true;
20 for (int uu : G[u]) {
21 if (!visit[uu]) {
22 dfs(uu);
23 }
24 if (inStk[uu])
25 low[u] = min(low[u], low[uu]);
26 }
27 if (visit[u] == low[u]) {
28 while (1) {
29 int uu = st.top();
30 st.pop();
31 inStk[uu] = false;
32 id[uu] = u;
33 if (uu == u) {
34 break;
35 }
36 }
37 }
38}
39
40vector<int> SCC(int n) {
41 inStk.resize(n);
42 visit.resize(n);
43 low.resize(n);
44 id.resize(n, -1);
45 t = 0;
46 for (int i = 0; i < n; i++) {
47 if (!visit[i]) {
48 dfs(i);
49 }
50 }
51 vector<int> ret;
52 for (int i = 0; i < n; i++) {
53 if (id[i] == i) {
54 ret.pb(i);
55 }
56 }
57 return ret;
58}
59
60int main() {
61 ios::sync_with_stdio(0), cin.tie(0);
62 int n, m;
63 cin >> n >> m;
64 G.resize(n);
65 for (int i = 0; i < m; i++) {
66 int a, b;
67 cin >> a >> b;
68 a--, b--;
69 G[a].pb(b);
70 }
71 auto ans = SCC(n);
72 if (ans.size() == 1) {
73 cout << "YES\n";
74 } else {
75 cout << "NO\n";
76 for (int i = 0; i < n; i++) {
77 for (int j : G[i]) {
78 if (id[i] != id[j]) {
79 cout << j + 1 << " " << i + 1 << "\n";
80 return 0;
81 }
82 }
83 }
84 // all components are SCC
85 cout << ans[0] + 1 << " " << ans[1] + 1 << "\n";
86 }
87 return 0;
88}
1087 - Shortest Subsequence
- 給一個字串 S,找一個最短字串 P 使得 P 不是 S 的子字串。
- Greedy。
1#pragma GCC optimization ("O3")
2#include<bits/stdc++.h>
3using namespace std;
4typedef long long ll;
5typedef pair<int, int> pii;
6#define pb push_back
7
8int main() {
9 ios::sync_with_stdio(0), cin.tie(0);
10 string s;
11 cin >> s;
12 vector<int> a(s.length());
13 for (int i = 0; s[i]; i++) {
14 if (s[i] == 'A') a[i] = 1;
15 else if (s[i] == 'C') a[i] = 2;
16 else if (s[i] == 'G') a[i] = 4;
17 else a[i] = 8;
18 }
19 int st = 0; // Bit Set
20 vector<int> ans;
21 for (int i = 0; i < a.size(); i++) {
22 st = st | a[i];
23 if (st == 15) {
24 st = 0;
25 ans.pb(a[i]);
26 }
27 }
28 for (int i = 1; i <= 8; i <<= 1) {
29 if ((st & i) == 0) {
30 ans.pb(i);
31 break;
32 }
33 }
34 string out = "";
35 for (int i = 0; i < ans.size(); i++) {
36 if (ans[i] == 1) out += "A";
37 else if (ans[i] == 2) out += "C";
38 else if (ans[i] == 4) out += "G";
39 else out += "T";
40 }
41 cout << out << "\n";
42 return 0;
43}
1756 - Acyclic Graph Edges
- 給一個無向圖,求輸出一個 Acyclic Orientation 的構造。
- Greedy 另小的點指向大的點,則必無環。
1#pragma GCC optimization ("O3")
2#include<bits/stdc++.h>
3using namespace std;
4int main() {
5 ios::sync_with_stdio(0), cin.tie(0);
6 int n, m;
7 cin >> n >> m;
8 for (int i = 0; i < m; i++) {
9 int a, b;
10 cin >> a >> b;
11 if (a > b) swap(a, b);
12 cout << a << " " << b << "\n";
13 }
14 return 0;
15}
1688 - Company Queries II
- LCA 模板題。
1#include<bits/stdc++.h>
2using namespace std;
3#pragma GCC optimization ("O3")
4#include<bits/stdc++.h>
5using namespace std;
6typedef long long ll;
7typedef pair<int, int> pii;
8#define pb push_back
9
10class SparseTableTarjan {
11 private:
12 int maxlg;
13 vector<vector<int>> anc;
14 vector<int> dep;
15 void dfs(int u, vector<vector<int>>& edge, int d) {
16 dep[u] = d;
17 for (int i = 1; i < maxlg; i++)
18 if (anc[u][i - 1] == -1) break;
19 else anc[u][i] = anc[anc[u][i - 1]][i - 1];
20 for (int a : edge[u]) {
21 if (dep[a] != -1) continue;
22 anc[a][0] = u;
23 dfs(a, edge, d + 1);
24 }
25 }
26 public:
27 SparseTableTarjan(vector<vector<int>>& edge, int root) {
28 int n = edge.size();
29 maxlg = ceil(log2(n));
30 anc.assign(n, vector<int>(maxlg, -1));
31 dep.assign(n, -1);
32 dfs(root, edge, 0);
33 }
34 int lca(int a, int b) {
35 if (dep[a] > dep[b]) swap(a, b);
36 for (int k = 0; dep[b] - dep[a]; k++)
37 if (((dep[b] - dep[a]) >> k) & 1) b = anc[b][k];
38 if (a == b) return a;
39 for (int k = maxlg - 1; k >= 0; k--)
40 if (anc[a][k] != anc[b][k])
41 a = anc[a][k], b = anc[b][k];
42 return anc[a][0];
43 }
44 int dist(int a, int b) {
45 return dep[a] + dep[b] - 2 * dep[lca(a, b)];
46 }
47};
48
49int main() {
50 ios::sync_with_stdio(0), cin.tie(0);
51 int n, q;
52 cin >> n >> q;
53 vector<vector<int>> G(n);
54 for (int i = 1; i < n; i++) {
55 int p;
56 cin >> p;
57 p--;
58 G[i].pb(p);
59 G[p].pb(i);
60 }
61 SparseTableTarjan ST(G, 0);
62 while (q--) {
63 int a, b;
64 cin >> a >> b;
65 cout << ST.lca(a - 1, b - 1) + 1 << "\n";
66 }
67 return 0;
68}
Josephus Problem I
1#pragma GCC optimization ("O3")
2#include<bits/stdc++.h>
3using namespace std;
4typedef long long ll;
5typedef pair<int, int> pii;
6#define pb push_back
7
8int main() {
9 ios::sync_with_stdio(0), cin.tie(0);
10 int n;
11 cin >> n;
12 if (n == 1) {
13 cout << "1\n";
14 return 0;
15 }
16 vector<bool> die(n);
17 cout << 2;
18 for (int i = 1, p = 0; i < n; i++) {
19 die[p] = true;
20 while(die[p]) {
21 p = (p + 1) % n;
22 }
23 p = (p + 1) % n;
24 while(die[p]) {
25 p = (p + 1) % n;
26 }
27 cout << ' ' << (p + 1) % n + 1;
28 }
29 cout << '\n';
30 return 0;
31}