16.0
1.《如 何 速 通 一 套 题》12.《如 何 速 通 一 套 题》23.《如 何 速 通 一 套 题》34.《如 何 速 通 一 套 题》 4.15.《如 何 速 通 一 套 题》5.06.《如 何 速 通 一 套 题》5.1bug fixed7.《如 何 速 通 一 套 题》6.08.《如 何 速 通 一 套 题》7.09.《如 何 速 通 一 套 题》8.010.《如 何 速 通 一 套 题》9.011.《如 何 速 通 一 套 题》 10.012.《如 何 速 通 一 套 题》12.013.《如 何 速 通 一 套 题》13.014.《如 何 速 通 一 套 题》14.015.标题,你懂的(15.0)...
16.16.0
邮寄
有史以来考的最好的一次。
开场秒 B。
A 想了一个做法。然后光速假掉,加了个三分勉强能行。
然后 cd 不会。
A
显然可以三分科技使用次数,然后 RMQ 计算答案。
#include <bits/stdc++.h> #define int long long using namespace std; struct node { int id, t; bool operator >(const node &b) const { return t > b.t; } }; int n, k, arr[100010], fa[100010][22], fw[100010][22]; vector<int> v; long long check(int x) { long long rs = 0; for(int i = 1; i <= n; i++) { int c = 0, t = i; for(int j = 20; j >= 0; j--) { if(c + fw[t][j] <= x) { c += fw[t][j]; t = fa[t][j]; } } rs += arr[t]; } return rs + k * x; } long long lmrm() { int l = 0, r = n + 2; long long ans = LLONG_MAX; for(; l <= r; ) { int len = (r - l) / 3; int lmid = l + len, rmid = r - len; if(check(lmid) <= check(rmid)) { ans = min(ans, check(lmid)); r = rmid - 1; }else { ans = min(ans, check(rmid)); l = lmid + 1; } } return ans; } signed main() { freopen("collect.in", "r", stdin); freopen("collect.out", "w", stdout); cin >> n >> k; for(int i = 1; i <= n; i++) { cin >> arr[i]; } rotate(arr + 1, min_element(arr + 1, arr + n + 1), arr + n + 1); for(int i = n; i >= 1; i--) { fw[i][0] = 100000000; for(; v.size() && arr[v.back()] > arr[i]; v.pop_back()) { fw[v.back()][0] = v.back() - i; fa[v.back()][0] = i; } v.push_back(i); } for(int i = 1; i <= n; i++) { for(int j = 1; j <= 20; j++) { fa[i][j] = fa[fa[i][j - 1]][j - 1]; fw[i][j] = fw[i][j - 1] + fw[fa[i][j - 1]][j - 1]; } } cout << lmrm() << '\n'; return 0; }
B
容斥,倍增。
#include <bits/stdc++.h> #define int long long using namespace std; struct node { int lc, rc; }ctl[200020], ctg[200020]; int n, arr[200020], fl[200020][22], fr[200020][22], rcl, rcg; long long ans; vector<int> v; // 5.1 Minimum, except in both void TVl(int x, int l, int r) { if(!x) { return ; } ans -= (r - l); int cl = x, cr = x; for(int i = 20; i >= 0; i--) { if(fl[cl][i] >= l) { cl = fl[cl][i]; ans += (1 << i); } if(fr[cr][i] <= r) { cr = fr[cr][i]; ans += (1 << i); } } TVl(ctl[x].lc, l, x - 1); TVl(ctl[x].rc, x + 1, r); } // 5.2 Maximum void TVg(int x, int l, int r) { if(!x) { return ; } ans -= (r - l); TVg(ctg[x].lc, l, x - 1); TVg(ctg[x].rc, x + 1, r); } signed main() { freopen("interval.in", "r", stdin); freopen("interval.out", "w", stdout); cin >> n; for(int i = 1; i <= n; i++) { cin >> arr[i]; } // 1. Cartesian, < for(int i = 1; i <= n; i++) { if(!v.size()) { v.push_back(i); continue; } for(; v.size() > 1 && arr[v.back()] > arr[i]; v.pop_back()) { ctl[i].lc = v.back(); } if(arr[v.back()] > arr[i]) { ctl[i].lc = v.back(); v.pop_back(); }else { ctl[v.back()].rc = i; } v.push_back(i); } rcl = v[0]; v.clear(); // 2. Cartesian, > for(int i = 1; i <= n; i++) { if(!v.size()) { v.push_back(i); continue; } for(; v.size() > 1 && arr[v.back()] < arr[i]; v.pop_back()) { ctg[i].lc = v.back(); } if(arr[v.back()] < arr[i]) { ctg[i].lc = v.back(); v.pop_back(); }else { ctg[v.back()].rc = i; } v.push_back(i); } rcg = v[0]; v.clear(); // 3. Left-first, > for(int i = n; i >= 1; i--) { for(; v.size() && arr[v.back()] < arr[i]; v.pop_back()) { fl[v.back()][0] = i; } v.push_back(i); } v.clear(); for(int i = 1; i <= n; i++) { for(int j = 1; j <= 20; j++) { fl[i][j] = fl[fl[i][j - 1]][j - 1]; } } /* for(int i = 1; i <= n; i++) { cout << fl[i][0] << ' '; } cout << '\n'; //*/ // 4. Right-first, > for(int i = 0; i <= 20; i++) { fr[n + 1][i] = n + 1; } for(int i = 1; i <= n; i++) { for(; v.size() && arr[v.back()] < arr[i]; v.pop_back()) { fr[v.back()][0] = i; } v.push_back(i); } for(int i = n; i >= 1; i--) { if(!fr[i][0]) { fr[i][0] = n + 1; } for(int j = 1; j <= 20; j++) { fr[i][j] = fr[fr[i][j - 1]][j - 1]; } } /* for(int i = 1; i <= n; i++) { cout << fr[i][0] << ' '; } cout << '\n'; //*/ // 5. Cal ans ans = 1ll * n * (n - 1) / 2; TVl(rcl, 1, n); TVg(rcg, 1, n); cout << ans << '\n'; return 0; } //Cartesian (<, >), Left-first with fa[200020][20], Right-first with fa[200020][20]
C
定义转移矩阵
然后就可以 121312141213121
做了。
答案矩阵
#include <bits/stdc++.h> using namespace std; const int kMod = int(1e9) + 7; struct node { int a[27][27]; node() { memset(a, 0, sizeof(a)); } auto operator [](int x) { return a[x]; } void init() { for(int i = 0; i <= 26; i++) { a[i][i] = 1; } } node operator *(node b) { node rs; for(int i = 0; i <= 26; i++) { for(int j = 0; j <= 26; j++) { for(int k = 0; k <= 26; k++) { rs[i][j] = (rs[i][j] + 1ll * a[i][k] * b[k][j]) % kMod; } } } return rs; } }; int n, ans; char c[550]; node convs(char c) { node rs; for(int i = 0; i <= 26; i++) { if(c - 'a' == i) { fill(rs[i], rs[i] + 27, 1); }else { rs[i][i] = 1; } } return rs; } node solve(int x) { if(x > n) { node tmp; tmp.init(); return tmp; } node tmp = solve(x + 1); return tmp * convs(c[x]) * tmp; } int main() { freopen("subseq.in", "r", stdin); freopen("subseq.out", "w", stdout); cin >> n; for(int i = 1; i <= n; i++) { cin >> c[i]; } node rs = solve(1); for(int i = 0; i < 26; i++) { ans = (ans + rs[i][26]) % kMod; } cout << ans << '\n'; return 0; }
D
首先建出 DFS 树。
显然,删除的两条边中必然有一条是树边。
注意:我们不考虑树边中存在桥的情况。
- 树+其他
此时,这个其他一定是唯一一个覆盖了这条树边的其他边。
- 树+树
此时,覆盖了这两个树边的的其他边的集合 相同。
然后,对于 2.,使用 xor hash 维护。
#include <bits/stdc++.h> #define st first #define nd second #define u64 unsigned long long #define int long long using namespace std; int n, m, k, u, v, is[200020], dfn[200020], low[200020], dcnt, cnt[200020], vis[200020]; long long ans; random_device rd; mt19937_64 mt(rd()); u64 sum[200020]; map<u64, int> mp; multiset<pair<int, int> > to[200020]; void DFS(int x, int pd) { dfn[x] = low[x] = ++dcnt; for(auto i : to[x]) { if(!dfn[i.st]) { DFS(i.st, i.nd); low[x] = min(low[x], low[i.st]); if(low[i.st] > dfn[x]) { is[i.st] = 1; } }else { if(i.nd != pd) { if(dfn[i.st] < dfn[x]) { int tmp = mt(); cnt[x]++, sum[x] ^= tmp; cnt[i.st]--, sum[i.st] ^= tmp; } low[x] = min(low[x], dfn[i.st]); } } } } void cal(int x) { vis[x] = 1; for(auto i : to[x]) { if(!vis[i.st]) { cal(i.st); cnt[x] += cnt[i.st]; sum[x] ^= sum[i.st]; } } } signed main() { //#ifndef LOCAL freopen("attack.in", "r", stdin); freopen("attack.out", "w", stdout); //#endif cin >> n >> m >> k; for(int i = 1; i <= m; i++) { cin >> u >> v; to[u].insert({v, i}); to[v].insert({u, i}); } if(k == 1) { DFS(1, 0); cout << accumulate(is + 1, is + n + 1, 0) << '\n'; }else { DFS(1, 0); cal(1); int cur = m; for(int i = 2; i <= n; i++) { if(is[i]) { ans += cur; cur--; }else { ans += (cnt[i] == 1); mp[sum[i]]++; } } for(auto i : mp) { ans += i.second * (i.second - 1) / 2; } cout << ans << '\n'; } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析