「賽後總結」20200827
阿新 • • 發佈:2020-08-27
考場上
先開 T1,emmm,感覺貪心很可做。開 T2,看懂題意 + 手玩樣例之後沒思路。開 T3,看懂題意 + 手玩樣例之後發現暴力修改暴力計算答案有 40pts 還是挺香的,寫了個暴力。
回頭看 T1,想起幾分鐘之前大佬說 9! 暴搜,有點猶豫寫貪心還是暴搜,因為不保證自己貪心的正確性打算放最後寫。
看 T2 沒思路,會 40pts 的暴力,寫了。
T1 想暴搜,列舉全排列,怎麼判斷和原序列相比交換了幾次?我淦,想不出來。寫了個看似正確能過樣例的貪心,跑路了。
預計得分:100 + 40 + 40 = 180
實際的分:0 + 40 + 40 = 80
出題人太狠了,把貪心卡的一分沒有。。。
T1
T2
T3
考場上的程式碼
#include <cstdio> #include <cstring> #include <string> #include <iostream> #include <algorithm> #define MAXN 50001 const int mod = 2019; int ans, n, m, pthn, head[MAXN], dep[MAXN]; int fa[MAXN][21], lg[MAXN], size[MAXN]; struct Edge { int next, to, w; }pth[MAXN]; void add(int from, int to, int w) { pth[++pthn].to = to, pth[pthn].next = head[from]; pth[pthn].w = w, head[from] = pthn; } void dfs(int u) { dep[u] = dep[fa[u][0]] + 1, size[u] = 1; for (int i = head[u]; i; i =pth[i].next) { int x = pth[i].to; if (x != fa[u][0]) { dfs(x); size[u] += size[x]; } } } void dfs1(int u, int k) { for (int i = head[u]; i; i = pth[i].next) { int x = pth[i].to; if (x != fa[u][0]) { dfs1(x, k); ans = (1ll * ans + 1ll * (size[k] - size[x]) * size[x] * pth[i].w % mod) % mod; } } } bool dfs2(int u, int x, int y, int k) { bool flag = false; for (int i = head[u]; i; i = pth[i].next) { int v = pth[i].to; if (dfs2(v, x, y, k)) { pth[i].w = (1ll * pth[i].w + k) % mod; flag = true; } } if (u == x || u == y) return true; return flag; } int lca(int x, int y) { if (dep[x] < dep[y]) std::swap(x, y); while (dep[x] > dep[y]) { x = fa[x][lg[dep[x] - dep[y]] - 1]; } if (x == y) return x; for (int k = lg[dep[x]] - 1; k >= 0; --k) { if (fa[x][k] != fa[y][k]) { x = fa[x][k]; y = fa[y][k]; } } return fa[x][0]; } int main() { freopen("network.in", "r", stdin); freopen("network.out", "w", stdout); scanf("%d %d", &n, &m); for (int i = 2, w; i <= n; ++i) { scanf("%d %d", &fa[i][0], &w); add(fa[i][0], i, w); } for (int i = 1; i <= n; ++i) { lg[i] = lg[i - 1] + ((1 << lg[i - 1]) == i); } dfs(1); for (int j = 1; (1 << j) <= n; ++j) { for (int i = 1; i <= n; ++i) { fa[i][j] = fa[fa[i][j - 1]][j - 1]; } } std::string opt; for (int i = 1, x, y, k; i <= m; ++i) { std::cin >> opt >> x; if (opt == "INC") { std::cin >> y >> k; int l = lca(x, y); dfs2(l, x, y, k); } else { ans = 0; dfs1(x, x); printf("%d\n", ans % mod); } } fclose(stdin), fclose(stdout); return 0; }
正解
#include <cstdio> #include <cstring> #include <string> #include <iostream> #include <algorithm> #define MAXN 50001 void read(int &T) { int x = 0; bool f = 0; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); } while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } T = f ? -x : x; } void write(int x) { if (x < 0) putchar('-'), write(-x); else { if (x / 10) write(x / 10); putchar(x % 10 + '0'); } } const int mod = 2019; int n, q, size[MAXN], w[MAXN], pre[MAXN], dfn[MAXN]; namespace Seg { #define lson now << 1 #define rson now << 1 | 1 struct Node { int l, r, sizz, siz; int sizw, sizzw, lazy; }tree[MAXN << 2]; void build(int l, int r, int now) { tree[now].l = l, tree[now].r = r; if (tree[now].l == tree[now].r) { tree[now].siz = size[pre[l]] % mod; tree[now].sizz = size[pre[l]] * size[pre[l]] % mod; tree[now].sizw = size[pre[l]] * w[pre[l]] % mod; tree[now].sizzw = w[pre[l]] * tree[now].sizz % mod; return; } int mid = (tree[now].l + tree[now].r) >> 1; build(l, mid, lson), build(mid + 1, r, rson); tree[now].sizz = (tree[lson].sizz + tree[rson].sizz) % mod; tree[now].siz = (tree[lson].siz + tree[rson].siz) % mod; tree[now].sizw = (tree[lson].sizw + tree[rson].sizw) % mod; tree[now].sizzw = (tree[lson].sizzw + tree[rson].sizzw) % mod; } void pushdown(int now) { if (tree[now].l == tree[now].r) return; tree[lson].lazy = (tree[lson].lazy + tree[now].lazy) % mod; tree[rson].lazy = (tree[rson].lazy + tree[now].lazy) % mod; tree[lson].sizw = (tree[lson].sizw + tree[lson].siz * tree[now].lazy) % mod; tree[lson].sizzw = (tree[lson].sizzw + tree[lson].sizz * tree[now].lazy % mod) % mod; tree[rson].sizw = (tree[rson].sizw + tree[rson].siz * tree[now].lazy) % mod; tree[rson].sizzw = (tree[rson].sizzw + tree[rson].sizz * tree[now].lazy % mod) % mod; tree[now].lazy = 0; } void update(int x, int y, int k, int now) { if (tree[now].l >= x && tree[now].r <= y) { tree[now].lazy = (tree[now].lazy + k) % mod; tree[now].sizw = (tree[now].sizw + tree[now].siz * k % mod) % mod; tree[now].sizzw = (tree[now].sizzw + tree[now].sizz * k % mod) % mod; return; } if (tree[now].lazy != 0) pushdown(now); int mid = (tree[now].l + tree[now].r) >> 1; if (x <= mid) update(x, y, k, lson); if (y > mid) update(x, y, k, rson); tree[now].sizw = (tree[lson].sizw + tree[rson].sizw) % mod; tree[now].sizzw = (tree[lson].sizzw + tree[rson].sizzw) % mod; } int query1(int x, int y, int now) { if (tree[now].l >= x && tree[now].r <= y) { return tree[now].sizw; } if (tree[now].lazy != 0) pushdown(now); int mid = (tree[now].l + tree[now].r) >> 1, ans = 0; if (x <= mid) ans = (ans + query1(x, y, lson)) % mod; if (y > mid) ans = (ans + query1(x ,y, rson)) % mod; return ans; } int query2(int x, int y, int now) { if (tree[now].l >= x && tree[now].r <= y) { return tree[now].sizzw; } if (tree[now].lazy != 0) pushdown(now); int mid = (tree[now].l + tree[now].r) >> 1, ans = 0; if (x <= mid) ans = (ans + query2(x, y, lson)) % mod; if (y > mid) ans = (ans + query2(x ,y, rson)) % mod; return ans; } } namespace Cut { int pthn, head[MAXN], fa[MAXN]; int cnt, dep[MAXN], son[MAXN], top[MAXN]; struct Edge { int next, to, w; }pth[MAXN]; void add(int from, int to, int w) { pth[++pthn].to = to, pth[pthn].next = head[from]; pth[pthn].w = w, head[from] = pthn; } void dfs1(int u, int father) { fa[u] = father, dep[u] = dep[father] + 1, size[u] = 1; for (int i = head[u]; i; i = pth[i].next) { int x = pth[i].to; if (x != fa[u]) { w[x] = pth[i].w; dfs1(x, u), size[u] += size[x]; if (size[son[u]] < size[x]) son[u] = x; } } } void dfs2(int u, int tp) { top[u] = tp, dfn[u] = ++cnt, pre[cnt] = u; if (son[u]) dfs2(son[u], tp); for (int i = head[u]; i; i = pth[i].next) { int x = pth[i].to; if (x != fa[u] && x != son[u]) dfs2(x, x); } } void change(int x, int y, int k) { while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) std::swap(x, y); Seg::update(dfn[top[x]], dfn[x], k, 1); x = fa[top[x]]; } if (dfn[x] > dfn[y]) std::swap(x, y); Seg::update(dfn[x] + 1, dfn[y], k, 1); } int ask(int node) { int ans1 = size[node] * Seg::query1(dfn[node] + 1, dfn[node] + size[node] - 1, 1) % mod; int ans2 = Seg::query2(dfn[node] + 1, dfn[node] + size[node] - 1, 1); return (ans1 - ans2 + mod) % mod; } } int main() { read(n), read(q); for (int i = 2, u, w; i <= n; ++i) { read(u), read(w); Cut::add(u, i, w); } Cut::dfs1(1, 0), Cut::dfs2(1, 1), Seg::build(1, n, 1); std::string opt; for (int i = 1, x, y, k; i <= q; ++i) { std::cin >> opt; read(x); if (opt == "INC") { read(y), read(k); Cut::change(x, y, k); } else { write(Cut::ask(x)); puts(""); } } return 0; }