2020.08.27考试解题报告
总结
今天考试就跟闹着玩一样,爆零了
别人都走了就只剩下我,我就没检查,然后 \(130->0\)
快乐死了,尼盟思乐
思路
T1
想法&&正解
爆搜,以为满分
然后因为一个变量 \(sum\) 写成 \(minn\) 然后就爆蛋了
T2
想法
没想法,考场没写,爆蛋了
正解
很奇怪,不明白正确性
%% zql 的题解
原题意中操作翻转任意连续 $k $ 盏灯可等价为
- 翻转 $1\sim k $ 盏灯
- 翻转距离为 $ k $ 的两盏灯(两次作一次)
操作 \(1\) 直接枚举
操作 \(2\) 中,可将灯分成 \(n/k\) 组,每组互不影响
若一组内熄灭的灯数为奇数,舍弃亮度最小的灯(偶数时可全打开)
T3
想法:
考试的时候打树剖做了一个小时发现自己读错题意了
然后我就傻逼以为树剖不能做,又去写树上差分,然后因为没取模爆蛋了
但是不知道为什么取模之后不是 \(40\) 而是 \(30\)……
正解:
树剖板子加点小技巧
在 \(x\) 的子树中,经过 \(i\) 的边有 \((siz[x] - siz[i]) \times siz[i]\) 条,证明略。
那么查询 \(x\) 子树的贡献就是:
\[\sum\limits_{i\in \text{x的子树}}w[i]\times(siz[x]-six[i])\times siz[i]
\]
化简:
\[\begin{aligned}&\sum\limits_{i\in \text{x的子树}}w[i]\times(siz[x]-six[i])\times siz[i]\\=&\sum\limits_{i\in\text{x的子树}}w[i]\times siz[i]\times siz[x]-\sum\limits_{i\in\text{x的子树}}w[i]\times siz[i]^2\\=&siz[x]\times\sum\limits_{i\in\text{x的子树}}w[i]\times siz[i]-\sum\limits_{i\in\text{x的子树}}w[i]\times siz[i]^2\end{aligned}
\]
只有 \(siz[x]\) 与 \(x\) 有关,所以可以用线段树维护一个点 \(i\) 的贡献,查询的时候随便艹一下就能做了,详情看代码
代码
T1
考场代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
const int A = 20;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int T, n, k, maxn, minn, tot, mmm;
int now[A], cnt, a[A], b[A];
void dfsmin(int k, int cnt) {
if(k <= 0 || cnt >= tot) {
int sum = 0;
for (int i = 1; i <= tot; i++)
sum = sum * 10 + a[i];
if (minn >= mmm) minn = min(minn, sum);
//debug:sum写成minn……100-->0
return;
}
for (int i = cnt + 1; i <= tot; i++)
if (a[i] <= a[cnt]) {
swap(a[i], a[cnt]);
dfsmin(k - 1, cnt + 1);
swap(a[i], a[cnt]);
}
dfsmin(k, cnt + 1);
}
void dfsmax(int k, int cnt) {
if (k <= 0 || cnt >= tot) {
int sum = 0;
for (int i = 1; i <= tot; i++)
sum = sum * 10 + b[i];
maxn = max(maxn,sum);
return;
}
for (int i = cnt + 1; i <= tot; i++)
if (b[i] >= b[cnt]) {
swap(b[i], b[cnt]);
dfsmax(k - 1, cnt + 1);
swap(b[i], b[cnt]);
}
dfsmax(k, cnt + 1);
}
inline void solve() {
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(now ,0, sizeof(now));
cnt = tot = 0;
n = read(), k = read();
minn = inf, maxn = 0;
while (n) now[++cnt] = n % 10, n /= 10;
mmm = 1;
for (int i = cnt; i; i--)
a[++tot] = now[i], b[tot] = now[i], mmm *= 10;
mmm /= 10;
dfsmin(k, 1), dfsmax(k, 1);
cout << maxn - minn << '\n';
}
signed main() {
T = read();
while (T--) solve();
return 0;
}
正解
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
const int A = 20;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int T, n, k, maxn, minn, tot, mmm;
int now[A], cnt, a[A], b[A];
void dfsmin(int k, int cnt) {
if(k <= 0 || cnt >= tot) {
int sum = 0;
for (int i = 1; i <= tot; i++)
sum = sum * 10 + a[i];
if (sum >= mmm) minn = min(minn, sum);
//debug:sum写成minn……100-->0
return;
}
for (int i = cnt + 1; i <= tot; i++)
if (a[i] <= a[cnt]) {
swap(a[i], a[cnt]);
dfsmin(k - 1, cnt + 1);
swap(a[i], a[cnt]);
}
dfsmin(k, cnt + 1);
}
void dfsmax(int k, int cnt) {
if (k <= 0 || cnt >= tot) {
int sum = 0;
for (int i = 1; i <= tot; i++)
sum = sum * 10 + b[i];
maxn = max(maxn,sum);
return;
}
for (int i = cnt + 1; i <= tot; i++)
if (b[i] >= b[cnt]) {
swap(b[i], b[cnt]);
dfsmax(k - 1, cnt + 1);
swap(b[i], b[cnt]);
}
dfsmax(k, cnt + 1);
}
inline void solve() {
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(now ,0, sizeof(now));
cnt = tot = 0;
n = read(), k = read();
minn = inf, maxn = 0;
while (n) now[++cnt] = n % 10, n /= 10;
mmm = 1;
for (int i = cnt; i; i--)
a[++tot] = now[i], b[tot] = now[i], mmm *= 10;
mmm /= 10;
dfsmin(k, 1), dfsmax(k, 1);
cout << maxn - minn << '\n';
}
signed main() {
T = read();
while (T--) solve();
return 0;
}
T2
正解
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int A = 1e5 + 11;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int n, k, zt[A], val[A], sum, ans, res;
inline void solve() {
memset(zt, 0, sizeof(zt));
memset(val, 0, sizeof(val));
n = read(), k = read();
sum = 0, ans = 0;
for (int i = 1; i <= n; i++) zt[i] = read();
for (int i = 1; i <= n; i++) val[i] = read(), sum += val[i];
res = sum;
for (int i = 1; i <= k; i++) {
int cnt = 0, minn = inf;
for (int j = i; j <= n; j += k) {
if (!zt[j]) cnt++;
minn = min(val[j], minn);
}
if (cnt & 1) res -= minn;
}
ans = max(ans, res);
for (int i = 1; i <= k; i++) zt[i] ^= 1;
res = sum;
for (int i = 1; i <= k; i++) {
int cnt = 0, minn = inf;
for (int j = i; j <= n; j += k) {
if (!zt[j]) cnt++;
minn = min(val[j], minn);
}
if (cnt & 1) res -= minn;
}
ans = max(ans, res);
cout << ans << '\n';
}
int main() {
int T = read();
while (T--) solve();
return 0;
}
T3
考场代码(加个取模吧)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int mod = 2019;
const int A = 6e5 + 11;
const int B = 1e6 + 11;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar(); int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int n, m, root, cnt, head[A], dis[A], ans = 0, val[A], nb[A];
int fa[A], dep[A], son[A], siz[A], c[A], top[A];
struct node { int to, nxt, val; } e[B << 1];
inline void add(int from, int to, int val) {
e[++cnt].to = to;
e[cnt].val = val;
e[cnt].nxt = head[from];
head[from] = cnt;
}
void prepare(int x, int f) {
dep[x] = dep[f] + 1, siz[x] = 1, fa[x] = f;
for (int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (to == f) continue;
prepare(to, x), siz[x] += siz[to];
if (siz[to] > siz[son[x]]) son[x] = to;
}
}
void dfs(int x, int tp) {
top[x] = tp;
if (son[x]) dfs(son[x], tp);
for (int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (to == fa[x] || to == son[x]) continue;
dfs(to, to);
}
}
inline int LCA(int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
return x;
}
void cnm(int x, int f) {
for (int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (to == f) continue;
cnm(to, x);
(nb[x] += nb[to]) %= mod;
}
}
void new_dfs(int x, int f, int now) {
for (int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (to == f) continue;
new_dfs(to, x, now);
ans += (e[i].val + nb[to]) * (siz[now] - siz[to]) * siz[to], ans %= mod;
}
}
int main() {
freopen("network.in", "r", stdin);
freopen("network.out", "w", stdout);
n = read(), m = read();
for (int i = 2; i <= n; i++) {
fa[i] = read(), c[i] = read();
add(fa[i], i, c[i]), add(i, fa[i], c[i]);
}
root = n;
while (fa[root]) root = fa[root];
prepare(root, 0), dfs(root, root);
char s[4];
int x, y, w, flag = 0;
while (m--) {
scanf("%s", s);
if (s[0] == 'I') {
flag = 1;
x = read(), y = read(), w = read();
int lca = LCA(x, y);
val[x] += w, val[y] += w, val[lca] -= 2 * w;
}
else if (s[0] == 'A') {
x = read();
if (flag) {
for (int i = 1; i <= n; i++) nb[i] = val[i];
cnm(root, 0);
}
ans = 0;
new_dfs(x, fa[x], x);
cout << ans % mod << '\n';
}
}
return 0;
}
正解
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int mod = 2019;
const int A = 6e5 + 11;
const int B = 1e6 + 11;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar(); int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int n, m, root, cnt, head[A];
struct node { int to, nxt, val; } e[B << 1];
inline void add(int from, int to, int val) {
e[++cnt].to = to;
e[cnt].val = val;
e[cnt].nxt = head[from];
head[from] = cnt;
}
int tot, fa[A], dep[A], son[A], siz[A], dfn[A], pre[A], c[A], top[A], w[A];
namespace Seg {
#define lson rt << 1
#define rson rt << 1 | 1
struct tree { int l, r, sum1, sum2, lazy, siz1, siz2; } t[A << 2];
//sum1 w[i] ×siz[i]
//sum2 w[i] ×siz[i]^2
inline void pushup(int rt) {
t[rt].sum1 = (t[lson].sum1 + t[rson].sum1) % mod;
t[rt].sum2 = (t[lson].sum2 + t[rson].sum2) % mod;
}
inline void pushdown(int rt) {
t[lson].lazy += t[rt].lazy, t[lson].lazy %= mod;
t[rson].lazy += t[rt].lazy, t[rson].lazy %= mod;
t[lson].sum1 += t[lson].siz1 * t[rt].lazy % mod, t[lson].sum1 %= mod;
t[lson].sum2 += t[lson].siz2 * t[rt].lazy % mod, t[lson].sum2 %= mod;
t[rson].sum1 += t[rson].siz1 * t[rt].lazy % mod, t[rson].sum1 %= mod;
t[rson].sum2 += t[rson].siz2 * t[rt].lazy % mod, t[rson].sum2 %= mod;
t[rt].lazy = 0;
}
void build(int rt, int l, int r) {
t[rt].l = l, t[rt].r = r, t[rt].lazy = 0;
if (l == r) {
t[rt].sum1 = w[pre[l]] * siz[pre[l]] % mod;
t[rt].sum2 = t[rt].sum1 * siz[pre[l]] % mod;
t[rt].siz1 = siz[pre[l]] % mod;
t[rt].siz2 = siz[pre[l]] * siz[pre[l]] % mod;
return;
}
int mid = (l + r) >> 1;
build(lson, l, mid), build(rson, mid + 1, r);
t[rt].siz1 = (t[lson].siz1 + t[rson].siz1) % mod;
t[rt].siz2 = (t[lson].siz2 + t[rson].siz2) % mod;
pushup(rt);
}
void update(int rt, int l, int r, int val) {
if (l <= t[rt].l && t[rt].r <= r) {
t[rt].sum1 = (t[rt].sum1 + t[rt].siz1 * val) % mod;
t[rt].sum2 = (t[rt].sum2 + t[rt].siz2 * val) % mod;
t[rt].lazy = (t[rt].lazy + val) % mod;
return;
}
if (t[rt].lazy) pushdown(rt);
int mid = (t[rt].l + t[rt].r) >> 1;
if (l <= mid) update(lson, l, r, val);
if (r > mid) update(rson, l, r, val);
pushup(rt);
}
int query(int rt, int l, int r) {
if (l <= t[rt].l && t[rt].r <= r) return t[rt].sum1 % mod;
if (t[rt].lazy) pushdown(rt);
int mid = (t[rt].l + t[rt].r) >> 1, ans = 0;
if (l <= mid) ans += query(lson, l, r), ans %= mod;
if (r > mid) ans += query(rson, l, r), ans %= mod;
return ans;
}
int query2(int rt, int l, int r) {
if (l <= t[rt].l && t[rt].r <= r) return t[rt].sum2 % mod;
if (t[rt].lazy) pushdown(rt);
int mid = (t[rt].l + t[rt].r) >> 1, ans = 0;
if (l <= mid) ans += query2(lson, l, r), ans %= mod;
if (r > mid) ans += query2(rson, l, r), ans %= mod;
return ans;
}
}
void prepare(int x, int f) {
dep[x] = dep[f] + 1, siz[x] = 1, fa[x] = f;
for (int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (to == f) continue;
w[to] = e[i].val;
prepare(to, x), siz[x] += siz[to];
if (siz[to] > siz[son[x]]) son[x] = to;
}
}
void dfs(int x, int tp) {
dfn[x] = ++tot, pre[tot] = x, top[x] = tp;
if (son[x]) dfs(son[x], tp);
for (int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (to == fa[x] || to == son[x]) continue;
dfs(to, to);
}
}
inline void add_qwq(int x, int y, int val) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
Seg::update(1, dfn[top[x]], dfn[x], val);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
Seg::update(1, dfn[x] + 1, dfn[y], val);
return;
}
inline int ask_qwq(int x) {
int ans1 = Seg::query(1, dfn[x] + 1, dfn[x] + siz[x] -1);
int ans2 = Seg::query2(1, dfn[x] + 1, dfn[x] + siz[x] - 1);
int ans = ans1 * siz[x] % mod - ans2;
ans = (ans % mod + mod) % mod;
return ans;
}
int main() {
n = read(), m = read();
for (int i = 2; i <= n; i++) {
fa[i] = read(), c[i] = read();
add(fa[i], i, c[i]), add(i, fa[i], c[i]);
}
root = 1;
while (fa[root]) root = fa[root];
prepare(root, 0), dfs(root, root), Seg::build(1, 1, n);
char s[4];
int x, y, w;
while (m--) {
scanf("%s", s);
if (s[0] == 'I') x = read(), y = read(), w = read(), add_qwq(x, y, w);
else if (s[0] == 'A') {
x = read();
if (x == 0) x = root;
cout << ask_qwq(x) << '\n';
}
}
return 0;
}
转载不必联系作者,但请声明出处