2024/09/22 模拟赛总结
没考,\(0+0+0+0=0\)。
当 \(Sum[l,r]>k(r-l+d+1)\) 是无解,移项得 \(\displaystyle\sum_{i=l}^{r}a_x-k>kd\)。
用线段树维护最大子段和,然后和 \(kd\) 比大小即可。
// BLuemoon_
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int kMaxN = 5e5 + 5;
LL ls(LL x) { return x << 1; }
LL rs(LL x) { return x << 1 | 1; }
struct SegmentTree {
LL c[kMaxN << 2], lm[kMaxN << 2], rm[kMaxN << 2], mx[kMaxN << 2];
void PushUp(int x) {
c[x] = c[ls(x)] + c[rs(x)], mx[x] = max({mx[ls(x)], mx[rs(x)], lm[rs(x)] + rm[ls(x)]});
lm[x] = max(lm[ls(x)], c[ls(x)] + lm[rs(x)]), rm[x] = max(rm[rs(x)], c[rs(x)] + rm[ls(x)]);
}
void Build(int x, int l, int r, LL k) {
if (l == r) {
c[x] -= k, lm[x] = rm[x] = mx[x] = c[x];
return;
}
int mid = (l + r) >> 1;
Build(ls(x), l, mid, k), Build(rs(x), mid + 1, r, k), PushUp(x);
}
void Update(int x, int l, int r, int ql, int qr) {
if (l == r) {
c[x] += qr, lm[x] = rm[x] = mx[x] = c[x];
return;
}
int mid = (l + r) >> 1;
mid >= ql ? Update(ls(x), l, mid, ql, qr) : Update(rs(x), mid + 1, r, ql, qr);
PushUp(x);
}
bool Query(LL p) {
return mx[1] <= p;
}
};
LL n, m, k, d, l, r;
SegmentTree tr;
void pr(bool pr) {
cout << (pr ? "YES" : "NO") << '\n';
}
int main() {
freopen("hire.in", "r", stdin);
freopen("hire.out", "w", stdout);
for (cin >> n >> m >> k >> d, tr.Build(1, 1, n - d, k); m; m--) {
cin >> l >> r, tr.Update(1, 1, n - d, l, r), pr(tr.Query(k * d));
}
return 0;
}
跳子可以抽象成 \(110\gets011,011\gets110\),即 \(11\) 和 \(0\) 交换位置。
用 \(dp_{i,j,k,0/1}\) 表示到了第 \(i\) 位,有 \(j\) 个 \(11\),\(k\) 个 \(0\),\(s_i\) 后接一个 \(1\) 能否变成 \(11\)。
对于每个 \(dp_{n,i,j_0/1}\),乘上 \(\mathrm{C}_{i+j}^{i}\)
注意需要滚掉一维
// BLuemoon_
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int kMaxN = 5e2 + 5;
const LL kP = 1e9 + 7;
LL n, dp[2][kMaxN][kMaxN][2], f[kMaxN], ans;
string s;
LL P(LL x, LL y, LL ret = 1) {
for (; y; (y & 1) && ((ret *= x) %= kP), (x *= x) %= kP, y >>= 1) {
}
return ret;
}
LL C(LL p, LL k) {
return f[p] * P(f[k] * f[p - k] % kP, kP - 2) % kP;
}
int main() {
freopen("checkers.in", "r", stdin), freopen("checkers.out", "w", stdout), f[0] = 1;
for (int i = 1; i < kMaxN; i++) {
f[i] = f[i - 1] * i % kP;
}
cin >> n >> s, s = ' ' + s, dp[0][0][0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= i; j++) {
for (int k = 0; k <= i; k++) {
for (int l = 0; l <= 1; l++) {
if (dp[0][j][k][l]) {
(s[i] == '0' || s[i] == '?') && ((dp[1][j][k + 1][0] += dp[0][j][k][l]) %= kP);
(s[i] == '1' || s[i] == '?') && (l ? (dp[1][j + 1][k][0] += dp[0][j][k][l]) %= kP : (dp[1][j][k][1] += dp[0][j][k][l]) %= kP);
}
}
}
}
for (int j = 0; j <= n; j++) {
for (int k = 0; k <= n; k++) {
for (int l = 0; l <= 1; l++) {
dp[0][j][k][l] = dp[1][j][k][l], dp[1][j][k][l] = 0;
}
}
}
}
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
LL e = (dp[0][i][j][0] + dp[0][i][j][1]) % kP;
(ans += (e * C(i + j, i))) %= kP;
}
}
cout << ans << '\n';
return 0;
}
令 \(dp_{i,j}\) 为树根为 \(i\),最后一个 \(dfn\) 为 \(j\) 的最大值。
// BLuemoon_
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int kMaxN = 1e5 + 5, kMaxM = 42 + 5;
int n;
LL ans, dp[kMaxN][kMaxM], a[kMaxN], tot, m, f[kMaxN], v[kMaxN], p[kMaxM][kMaxM], l[kMaxM], r[kMaxM];
vector<int> g[kMaxN];
void DFS(int u, LL ret = -1e18) {
dp[u][f[u]] = a[u];
for (int v : g[u]) {
DFS(v);
for (int i = 0; i <= tot; i++) {
(!p[i][f[v]]) && (ret = max(ret, dp[u][i]));
}
for (int i = 0; i <= tot; i++) {
dp[u][i] = max(dp[u][i], dp[v][i] + ret);
}
}
}
int main() {
freopen("block.in", "r", stdin);
freopen("block.out", "w", stdout);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
if (*max_element(a + 1, a + n + 1) <= 0) {
cout << *max_element(a + 1, a + n + 1) << '\n';
return 0;
}
for (int i = 1, sz, x; i <= n; i++) {
for (cin >> sz; sz; sz--) {
cin >> x, g[i].push_back(x);
}
}
for (int i = 1; i <= m; i++) {
cin >> l[i] >> r[i], v[l[i]] = v[r[i]] = 1;
}
for (int i = 1; i <= n; i++) {
v[i] && (f[i] = ++tot);
}
for (int i = 1; i <= m; i++) {
p[f[l[i]]][f[r[i]]] = p[f[r[i]]][f[l[i]]] = 1;
}
fill(dp[0], dp[kMaxN - 1], -1e18), DFS(1), ans = -1e18;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= tot; j++) {
ans = max(ans, dp[i][j]);
}
}
cout << ans << '\n';
return 0;
}

浙公网安备 33010602011771号