Comet OJ - Contest #9 & X Round 3 CD题解

C. 【XR-3】核心城市

树直径签到题
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
vector<int> G[maxn];
int dep[maxn], rt, o, dp[maxn];
void dfs(int u, int fa) {
    dep[u] = dep[fa] + 1;
    dp[u] = 1;
    if (dep[u] > dep[rt])
        rt = u;
    for (auto v : G[u])
        if (v != fa) {
            dfs(v, u);
            dp[u] = max(dp[u], dp[v] + 1);
        }
    if (dp[u] == (dep[rt] + 1) / 2)
        o = u;
}
int main() {
    int n, k, u, v;
    scanf("%d%d", &n, &k);
    for (int i = 1; i < n; i++) {
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1, 0);
    dfs(rt, 0);
    dfs(o, 0);
    sort(dp + 1, dp + 1 + n);
    printf("%d\n", dp[n - k]);
}

D.【XR-3】系统设计

解法:我们先对每个节点的出边按儿子的编号排序,然后每个儿子都会得到一个顺序 k k ,将树重链剖分,每个点对应的 h a s h hash 值是重儿子顺序 k p [ d f n ] k*p[dfn] ,然后维护每条重链的 h a s h hash 值,同时用树状数组动态维护 a a 序列 h a s h hash 值,每次查询操作,我们从 x x 节点,顺着它的重链通过hash二分找到其与 a a 序列的 l c p lcp ,然后我们跳到 l c p lcp 的那个节点继续操作即可。明天再试试线段树解法
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define low(x) x&-x
using namespace std;
const int maxn = 5e5 + 10, base = 998244353;
ull p[maxn];
vector<int> G[maxn];
int a[maxn], sz[maxn], son[maxn], pos[maxn], cnt;
int id[maxn], rk[maxn], f[maxn], bot[maxn], n;
struct HASH {
    ull c[maxn];
    void up(int x, ull v) {
        v *= p[x];
        for (; x <= n; x += low(x))
            c[x] += v;
    }
    ull qu(int x) {
        ull res = 0;
        for (; x; x -= low(x))
            res += c[x];
        return res;
    }
    ull query(int l, int r) {
        ll res = qu(r) - qu(l - 1);
        return res * p[n - l];
    }
} T1, T2;
void dfs1(int u, int fa) {
    sz[u] = 1;
    f[u] = fa;
    sort(G[u].begin(), G[u].end());
    int i = 0;
    for (auto v : G[u]) {
        dfs1(v, u);
        sz[u] += sz[v];
        ++i;
        if (sz[son[u]] < sz[v])
            son[u] = v, pos[u] = i;
    }
}
void dfs2(int u, int top) {
    id[u] = ++cnt;
    rk[cnt] = u;
    if (!son[u]) {
        bot[u] = u;
        T1.up(id[u], -9102);
        return;
    }
    else {
        dfs2(son[u], top);
        bot[u] = bot[son[u]];
    }
    T1.up(id[u], pos[u]);
    for (auto v : G[u])
        if (v != son[u])
            dfs2(v, v);
}
int lcp(int l1, int r1, int l2, int r2) {
    int L = 0, R = min(r1 - l1 + 1, r2 - l2 + 1);
    while (L < R) {
        int m = (L + R) / 2;
        if (T1.query(l1, l1 + m) != T2.query(l2, l2 + m))
            R = m;
        else
            L = m + 1;
    }
    return L;
}
int gao(int x, int l, int r) {
    int L = id[x], R = id[bot[x]];
    while (l <= r) {
        int k = lcp(L, R, l, r);
        l += k;
        int o = rk[L + k];
        if (l > r || a[l] > G[o].size())
            return o;
        x = G[o][a[l] - 1];
        l++;
        if (l > r)
            return x;
        L = id[x];
        R = id[bot[x]];
    }
}
int main() {
    p[0] = 1;
    for (int i = 1; i < maxn; i++)
        p[i] = p[i - 1] * base;
    int m, q, l, r, opt, x, rt;
    scanf("%d%d%d", &n, &m, &q);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &x);
        if (x)
            G[x].push_back(i);
        else
            rt = i;
    }
    for (int i = 1; i <= m; i++) {
        scanf("%d", &a[i]);
        T2.up(i, a[i]);
    }
    dfs1(rt, 0);
    dfs2(rt, rt);
    while (q--) {
        scanf("%d", &opt);
        if (opt == 1) {
            scanf("%d%d%d", &x, &l, &r);
            printf("%d\n", gao(x, l, r));
        }
        else {
            scanf("%d%d", &l, &x);
            T2.up(l, x - a[l]);
            a[l] = x;
        }
    }
}
发布了302 篇原创文章 · 获赞 98 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/ccsu_cat/article/details/100111667