ccf csp 202012-1
A 期末预测之安全指数
签到
B 期末预测之最佳阈值
签到
排序之后, 处理前缀和, 先行枚举
C 带配额的文件系统
D 食材运输
注意到食材就10种, 直接状压,
又发现答案单调, 直接二分
const int N = 1e2, M = 10;
int n, m, _, k, cas;
int a[N][M], d[N][M], v[N], f[1 << M];
vector<PII> h[N];
PII dfs(int x, int fa, int k) {
int res = 0, mx = 0;
for (auto& [y, c] : h[x]) if (y ^ fa) {
auto cur = dfs(y, x, k);
if (~cur.fi) res += cur.fi + c * 2, umax(mx, cur.se + c);
}
return res ? PII{ res - (_ == x) * mx, mx } : a[x][k] ? PII{ 0, 0 } : PII{ -1, 0 };
}
bool check(int mid) {
memset(v, 0, sizeof v); memset(f, 0x3f, sizeof f); f[0] = 0;
rep(i, 0, n - 1) rep(j, 0, k - 1) if (~d[i][j] && d[i][j] <= mid) v[i] |= 1 << j;
rep(i, 0, n - 1) rep(j, 0, (1 << k) - 1) umin(f[j | v[i]], f[j] + 1);
return f[(1 << k) - 1] <= m;
}
int main() {
IOS; cin >> n >> m >> k;
rep(i, 0, n - 1) rep(j, 0, k - 1) cin >> a[i][j];
rep(i, 2, n) { int u, v, c; cin >> u >> v >> c; --u, --v; h[u].pb(v, c); h[v].pb(u, c); }
rep(i, 0, n - 1) { _ = i; rep(j, 0, k - 1) d[i][j] = dfs(i, -1, j).fi; }
int l = 0, r = 1e8;
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << l;
return 0;
}
E 星际旅行
线段树基操, 只不过是维护3个序列, 注意标记下压顺序, 先旋转, 再区间乘, 再区间加
const int N = 4e4 + 5, mod = 1e9 + 7;
struct query { ll op, l, r, x[3]; } a[N];
struct BIT {
struct node { int l, r, c; ll val[3], tag[5]; } tr[N * 40];
void push_up(int rt) { rep(i, 0, 2) tr[rt].val[i] = (tr[rt << 1].val[i] + tr[rt << 1 | 1].val[i]) % mod; }
void push_down(int rt) {
if (tr[rt].tag[4] == 1)
swap(tr[rt << 1].val[0], tr[rt << 1].val[1]), swap(tr[rt << 1].val[1], tr[rt << 1].val[2]),
swap(tr[rt << 1].tag[0], tr[rt << 1].tag[1]), swap(tr[rt << 1].tag[1], tr[rt << 1].tag[2]),
swap(tr[rt << 1 | 1].val[0], tr[rt << 1 | 1].val[1]), swap(tr[rt << 1 | 1].val[1], tr[rt << 1 | 1].val[2]),
swap(tr[rt << 1 | 1].tag[0], tr[rt << 1 | 1].tag[1]), swap(tr[rt << 1 | 1].tag[1], tr[rt << 1 | 1].tag[2]);
if (tr[rt].tag[4] == 2)
swap(tr[rt << 1].val[0], tr[rt << 1].val[2]), swap(tr[rt << 1].val[1], tr[rt << 1].val[2]),
swap(tr[rt << 1].tag[0], tr[rt << 1].tag[2]), swap(tr[rt << 1].tag[1], tr[rt << 1].tag[2]),
swap(tr[rt << 1 | 1].val[0], tr[rt << 1 | 1].val[2]), swap(tr[rt << 1 | 1].val[1], tr[rt << 1 | 1].val[2]),
swap(tr[rt << 1 | 1].tag[0], tr[rt << 1 | 1].tag[2]), swap(tr[rt << 1 | 1].tag[1], tr[rt << 1 | 1].tag[2]);
if (tr[rt].tag[3] ^ 1) rep(i, 0, 2)
tr[rt << 1].val[i] = tr[rt << 1].val[i] * tr[rt].tag[3] % mod,
tr[rt << 1].tag[i] = tr[rt << 1].tag[i] * tr[rt].tag[3] % mod,
tr[rt << 1 | 1].val[i] = tr[rt << 1 | 1].val[i] * tr[rt].tag[3] % mod,
tr[rt << 1 | 1].tag[i] = tr[rt << 1 | 1].tag[i] * tr[rt].tag[3] % mod;
rep(i, 0, 2) if (tr[rt].tag[i])
tr[rt << 1].val[i] = (tr[rt << 1].val[i] + tr[rt].tag[i] * tr[rt << 1].c % mod) % mod,
tr[rt << 1].tag[i] = (tr[rt << 1].tag[i] + tr[rt].tag[i]) % mod,
tr[rt << 1 | 1].val[i] = (tr[rt << 1 | 1].val[i] + tr[rt].tag[i] * tr[rt << 1 | 1].c % mod) % mod,
tr[rt << 1 | 1].tag[i] = (tr[rt << 1 | 1].tag[i] + tr[rt].tag[i]) % mod;
tr[rt << 1].tag[3] = tr[rt << 1].tag[3] * tr[rt].tag[3] % mod;
tr[rt << 1 | 1].tag[3] = tr[rt << 1 | 1].tag[3] * tr[rt].tag[3] % mod;
tr[rt << 1].tag[4] = (tr[rt << 1].tag[4] + tr[rt].tag[4]) % 3;
tr[rt << 1 | 1].tag[4] = (tr[rt << 1 | 1].tag[4] + tr[rt].tag[4]) % 3;
memset(tr[rt].tag, 0, sizeof tr[rt].tag); tr[rt].tag[3] = 1;
}
void build(int rt, int l, int r, vector<int>& c) {
tr[rt].l = l, tr[rt].r = r, tr[rt].c = c[r + 1] - c[l];
memset(tr[rt].val, 0, sizeof tr[rt].val);
memset(tr[rt].tag, 0, sizeof tr[rt].tag); tr[rt].tag[3] = 1;
if (l == r) return;
int mid = l + r >> 1;
build(rt << 1, l, mid, c); build(rt << 1 | 1, mid + 1, r, c);
}
void change(int rt, query& q) {
if (tr[rt].l >= q.l && tr[rt].r <= q.r) {
if (q.op == 1) rep(i, 0, 2)
tr[rt].val[i] = (tr[rt].val[i] + q.x[i] * tr[rt].c % mod) % mod, tr[rt].tag[i] = (tr[rt].tag[i] + q.x[i]) % mod;
else if (q.op == 2) {
rep(i, 0, 2) tr[rt].val[i] = tr[rt].val[i] * q.x[0] % mod, tr[rt].tag[i] = tr[rt].tag[i] * q.x[0] % mod;
tr[rt].tag[3] = tr[rt].tag[3] * q.x[0] % mod;
}
else {
swap(tr[rt].val[0], tr[rt].val[1]), swap(tr[rt].val[1], tr[rt].val[2]);
swap(tr[rt].tag[0], tr[rt].tag[1]), swap(tr[rt].tag[1], tr[rt].tag[2]);
tr[rt].tag[4] = (tr[rt].tag[4] + 1) % 3;
}
return;
}
push_down(rt); int mid = tr[rt].l + tr[rt].r >> 1;
if (mid >= q.l) change(rt << 1, q);
if (mid < q.r) change(rt << 1 | 1, q);
push_up(rt);
}
query ask(int rt, int l, int r) {
query ans, res;
if (tr[rt].l >= l && tr[rt].r <= r) return memcpy(ans.x, tr[rt].val, sizeof ans.x), ans;
push_down(rt); int mid = tr[rt].l + tr[rt].r >> 1;
if (mid >= l) ans = ask(rt << 1, l, r);
else memset(ans.x, 0, sizeof ans.x);
if (mid < r) { res = ask(rt << 1 | 1, l, r); rep(i, 0, 2) ans.x[i] = (ans.x[i] + res.x[i]) % mod; }
return ans;
}
} bit;
int n, m, _, k, cas;
vector<int> c;
int main() {
IOS; cin >> n >> m;
rep(i, 1, m) {
cin >> a[i].op >> a[i].l >> a[i].r; c.pb(a[i].l); c.pb(a[i].r + 1);
if (a[i].op == 1) cin >> a[i].x[0] >> a[i].x[1] >> a[i].x[2];
else if (a[i].op == 2) cin >> a[i].x[0];
}
sort(all(c)); c.erase(unique(all(c)), c.end());
bit.build(1, 0, c.size() - 1, c);
rep(i, 1, m) {
a[i].l = lower_bound(all(c), a[i].l) - c.begin(); a[i].r = upper_bound(all(c), a[i].r) - c.begin() - 1;
if (a[i].op ^ 4) bit.change(1, a[i]);
else {
a[i] = bit.ask(1, a[i].l, a[i].r); ll ans = 0;
rep(j, 0, 2) ans = (ans + sqr(a[i].x[j])) % mod;
cout << ans << '\n';
}
}
return 0;
}