使用 dp(i) 表示当打开前 i 根管子,需要多久才能把前 i 个水库放满。转移方程为:dp(i)=max(dp(i−1),⌈prei/i⌉),其中 pre 数组表示前缀和。转移方程中第二个参数为水库总量除以水管数上取整,显然这是所需时间的下界。同时由于前 i−1 个水库只能由前 i−1 根水管填满,所以需要考虑前 i−1 个水库的情况。
基于此,我们可以直接得到打开 i 根水管填满 n 个水库所需的时间:max(dp(i),⌈pren/i⌉),其含义与转移方程基本一致。
#include<bits/stdc++.h> #define endl '\n' usingnamespace std; constint N = 1e5 + 10, M = 4 * N;
int n, m; int a[N];
int head[N], ne[M], edge[M], weight[M], tot = 1;
voidadd(int a, int b, int c) { edge[++tot] = b, weight[tot] = c; ne[tot] = head[a], head[a] = tot; }
voidsolve(int k)// k-th bit { for (int i = 1; i <= n; i++) a[i] |= 1 << k; // 首先找到所有或为 0 的边,将所有点置 0 for (int i = 2; i <= tot; i += 2) { int x = edge[i]; int y = edge[i + 1]; if ((weight[i] & (1 << k)) == 0) a[x] &= ~(1 << k), a[y] &= ~(1 << k); } for (int i = 1; i <= n; i++) { // 考虑能否置零,置 0 后是否会出现矛盾(另一顶点的对应位置也是0) bool flag = true; for (int j = head[i]; ~j; j = ne[j]) { if ((weight[j] & (1 << k)) == 0) continue; int y = edge[j]; if ((a[y] & (1 << k)) == 0 || i == y) { flag = false; break; } } if (flag) a[i] &= ~(1 << k); } }
intmain() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); memset(head, -1, sizeof(head)); cin >> n >> m; while (m--) { int a, b, c; cin >> a >> b >> c; add(a, b, c); add(b, a, c); } for (int i = 0; i < 30; i++) solve(i); for (int i = 1; i <= n; i++) cout << a[i] << " "; }
voidup(int p) { while (p > 1) { if (heap[p].r < heap[p / 2].r) { swap(heap[p], heap[p / 2]); p /= 2; } else break; } }
voiddown(int p) { int s = 2 * p; while (s <= tot) { if (s < tot && heap[s + 1].r < heap[s].r) s++; if (heap[s].r < heap[p].r) { swap(heap[s], heap[p]); p = s, s = 2 * p; } else break; } }
voidinsert(Range x) { heap[++tot] = x; up(tot); }
Range extract() { Range a = heap[1]; heap[1] = heap[tot--]; down(1); return a; }
path.push_back(0); int t; cin >> t; while (t--) { memset(head, -1, sizeof(head)); tot = 0; cin >> n; for (int i = 2; i <= n; i++) { int p, a, b; cin >> p >> a >> b; add(p, i, a, b); }
for (int i = head[1]; ~i; i = ne[i]) { int v = edge[i]; sa[v] = A[i]; path.push_back(B[i]); dfs(v); path.pop_back(); } for (int i = 2; i <= n; i++) cout << ans[i] << " "; cout << endl; } }
booldfs(int k, int p = -1)// 目前的数列是否能构成前 n 项fib数列 { if (k == 0) returntrue; for (int i = 1; i <= n; i++) { if (i == p) // 不能重复使用相同的字母 continue; if (a[i] >= fib[k]) { a[i] -= fib[k]; if (dfs(k - 1, i)) returntrue; a[i] += fib[k]; } } returnfalse; }
intmain() { ios::sync_with_stdio(false); cin.tie(nullptr); for (tot = 1; get_fib(tot) <= 1e9; tot++) prefib[tot] = prefib[tot - 1] + fib[tot]; int t; cin >> t; while (t--) { ll sum = 0; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i], sum += a[i]; int fib_n = 0; // 找到字符串对应前 fib_n 项fib数列 for (int i = 1; i <= tot; i++) if (sum == prefib[i]) { fib_n = i; break; } if (fib_n == 0) cout << "NO" << endl; else { bool flag = dfs(fib_n); cout << (flag ? "YES" : "NO") << endl; } } }
int t; cin >> t; while (t--) { int n; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i], p[i] = p[i - 1] ^ a[i]; st.clear(); st.insert(0); int ans = n; for (int i = 1; i <= n; i++) { if (st.count(p[i])) { ans--; st.clear(); } st.insert(p[i]); } cout << ans << endl; } }
#include<bits/stdc++.h> #define endl '\n' usingnamespace std; using ll = longlong; constint N = 1e5 + 10;
int n, k; ll a[N]; ll b[N];
boolcheck(ll ans) { // 若答案为ans,则满足 // all a[i] >= ans/2 // min(a[i],a[i+1]) >= ans memcpy(b, a, (n + 1) * sizeof(ll)); int p = k; for (int i = 1; i <= n; i++) if (b[i] * 2 < ans) b[i] = 1e9, p--; if (p < 0) returnfalse; elseif (p == 0) { ll res = 0; for (int i = 1; i < n; i++) res = max(res, min(b[i], b[i + 1])); return res >= ans; } elseif (p == 1) { ll res = 0; for (int i = 1; i <= n; i++) res = max(res, b[i]); return res >= ans; } else returntrue; }
intmain() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int t; cin >> t; while (t--) { cin >> n >> k; for (int i = 1; i <= n; i++) cin >> a[i]; ll l = 1, r = 1e9; while (l < r) { ll mid = (l + r + 1) / 2; if (check(mid)) l = mid; else r = mid - 1; } cout << l << endl; } }
#include<bits/stdc++.h> #define endl '\n' usingnamespace std; constint N = 2e5 + 10, M = 2 * N;
int n, q, k; int head[N], ne[M], edge[M], tot = 0; int depth[N]; set<int> st; int f[N][19];
voidadd(int a, int b) { edge[++tot] = b; ne[tot] = head[a], head[a] = tot; }
voidbuild() { queue<int> q; q.push(1); depth[1] = 1; while (q.size()) { int u = q.front(); q.pop(); for (int i = head[u]; ~i; i = ne[i]) { int v = edge[i]; if (depth[v]) continue; depth[v] = depth[u] + 1; f[v][0] = u; for (int j = 1; j < 19; j++) f[v][j] = f[f[v][j - 1]][j - 1]; q.push(v); } } }
intlca(int x, int y) { if (depth[x] > depth[y]) swap(x, y); for (int i = 18; i >= 0; i--) if (depth[f[y][i]] >= depth[x]) y = f[y][i]; if (x == y) return x; for (int i = 18; i >= 0; i--) if (f[x][i] != f[y][i] && f[x][i] != 0) x = f[x][i], y = f[y][i]; return f[x][0]; }
#include<bits/stdc++.h> #define endl '\n' usingnamespace std; using ll = longlong; constint N = 2e5 + 10;
int n, w, m; char str[N]; vector<int> mp[9]; ll pre[N];
intmain() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int t; cin >> t; while (t--) { for (int i = 0; i < 9; i++) mp[i].clear(); cin >> (str + 1); n = strlen(str + 1); cin >> w >> m; for (int i = 1; i <= n; i++) pre[i] = (pre[i - 1] + str[i] - '0') % 9; for (int i = 1; i + w - 1 <= n; i++) { // 计算每段的数值 ll sum = (pre[i + w - 1] - pre[i - 1] + 9) % 9; if (mp[sum].size() < 2) mp[sum].push_back(i); } while (m--) { int l, r, k; cin >> l >> r >> k; ll sum = (pre[r] - pre[l - 1] + 9) % 9; int a = 0x3f3f3f3f, b = 0x3f3f3f3f; for (int i = 0; i < 9; i++) for (int j = 0; j < 9; j++) { if (mp[i].size() == 0 || mp[j].size() == 0) continue; if ((i * sum + j) % 9 == k) { if (i == j && mp[i].size() == 2 && (a > mp[i][0] || a == mp[i][0] && b > mp[i][1])) a = mp[i][0], b = mp[i][1]; elseif (i != j && (a > mp[i][0] || a == mp[i][0] && b > mp[j][0])) a = mp[i][0], b = mp[j][0]; } } if (a == 0x3f3f3f3f && b == 0x3f3f3f3f) cout << -1 << " " << -1 << endl; else cout << a << " " << b << endl; } } }
#include<bits/stdc++.h> #define endl '\n' usingnamespace std; using ll = longlong; using PII = pair<ll, ll>; constint N = 2e5 + 10;
int n, m; ll a[N]; ll p[N];
voidsolve() { for (int i = 1; i <= n; i++) p[i] = a[i] + p[i - 1]; vector<PII> L, R; int l = m - 1, r = m + 1; // 检测 [i, l] 是否构成一个 good group // 即 p[l]-p[i-1] >= 0 for (int i = m - 1; i >= 1; i--) { if (p[l] - p[i - 1] >= 0 || i == 1) { ll cur = 0, worst = 0; for (int j = l; j >= i; j--) { cur += a[j]; worst = min(cur, worst); } L.push_back({cur, -worst}); l = i - 1; } }
// 检测 [r, i] 是否构成一个good group // 即 p[i] - p[r - 1] >= 0 for (int i = m + 1; i <= n; i++) { if (p[i] - p[r - 1] >= 0 || i == n) { ll cur = 0, worst = 0; for (int j = r; j <= i; j++) { cur += a[j]; worst = min(worst, cur); } R.push_back({cur, -worst}); r = i + 1; } }