• WC2013 糖果公园


    树上每个点有颜色,每个颜色有一个关于出现次数的权值,定义一条路径的权值为 $sum$ 路径上每个点权值 $ imes$ 它的颜色在路径上出现次数的权值

    给 $q$ 次操作,每次修改一个点的颜色或者询问一条路径的权值

    $n leq 100000$

    sol:

    bzoj 200s 极度酸爽

    只被我卡了一个人,极度差评

    这题如果没有单点修改,是一个树上莫队题,如果有单点修改,就是一个树上带修改莫队题

    于是都来写一写:

    树上莫队,首先王室联邦分块,维护一下每个点在不在当前路径上

    每次暴力爬 $(c_u,q_u),(c_v,q_v)$ 这两条路径修改,最后单算一下 $LCA(q_u,q_v)$ 的贡献即可

    带修改莫队,就是在每个询问操作的时候维护一个时间戳,也维护一个当前时间戳,每次把当前时间戳移动到操作时间戳即可

    移动时顺便计算/消除每次修改操作的影响,如果有影响,就直接加上去,然后把修改操作改成反向修改操作

    这题把这俩东西整到一起就可以了

    这份代码很慢,还有可以卡的地方:O(1) lca,使用欧拉序分块,fread,指令集

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
    #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
    using namespace std;
    inline int read() {
        int x = 0, f = 1; char ch;
        for (ch = getchar(); !isdigit(ch); ch = getchar()) if (ch == '-') f = -f;
        for (; isdigit(ch); ch = getchar()) x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 100010;
    int n, m, nq, sz, v[maxn], w[maxn], c[maxn];
    int first[maxn], to[maxn << 1], nx[maxn << 1], cnt;
    inline void add(int u, int v) {
        to[++cnt] = v;
        nx[cnt] = first[u];
        first[u] = cnt;
    }
    int size[maxn], fa[maxn], top[maxn], dep[maxn];
    inline void sp_dfs1(int x) {
        size[x] = 1;
        for(int i=first[x];i;i=nx[i]) {
            if(to[i] == fa[x]) continue;
            fa[to[i]] = x; dep[to[i]] = dep[x] + 1;
            sp_dfs1(to[i]); size[x] += size[to[i]];
        }
    }
    inline void sp_dfs2(int x, int col) {
        int k = 0; top[x] = col;
        for(int i=first[x];i;i=nx[i])
            if(to[i] != fa[x] && size[to[i]] > size[k]) k = to[i];
        if(!k) return; sp_dfs2(k, col);
        for(int i=first[x];i;i=nx[i])
            if(to[i] != fa[x] && to[i] != k) sp_dfs2(to[i], to[i]);
    }
    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]];
        }
        return dep[x] < dep[y] ? x : y;
    }
    int q[maxn], tp, bl[maxn], bcnt;
    int fk_dfs(int x) {
        int cur = 0;
        for(int i=first[x];i;i=nx[i]) {
            int v = to[i]; if(v == fa[x]) continue;
            cur += fk_dfs(v);
            if(cur >= sz) {
                bcnt++;
                while(cur--) bl[q[--tp]] = bcnt;
            }
        }
        q[++tp] = x;
        return cur + 1;
    }
    struct Ques {
        int u, v, fu, fv, id, t;
        Ques(){}
        Ques(int _1, int _2, int _3, int _4, int _5, int _6): u(_1), v(_2), fu(_3), fv(_4), id(_5), t(_6){}
        bool operator < (const Ques &b) const {
            if(fu == b.fu) {
                if(fv == b.fv) return t < b.t;
                return fv < b.fv;
            }return fu < b.fu;
        }
    }qs[maxn];
    struct Chg {
        int pos, val;
        Chg(){}
        Chg(int _1, int _2): pos(_1), val(_2){}
    }cs[maxn];
    int pnt[maxn], vis[maxn];
    int qcnt, ccnt, iter;
    LL ans[maxn], now;
    inline void opt(int x) {
        if(vis[x]) {
            now -= 1LL * v[c[x]] * w[pnt[c[x]]];
            pnt[c[x]]--;
        }
        else {
            pnt[c[x]]++;
            now += 1LL * v[c[x]] * w[pnt[c[x]]];
        }
        vis[x] ^= 1;
    }
    inline void move(int &x) { opt(x); x = fa[x]; }
    inline void change(int tim) {
        if(vis[cs[tim].pos]) {
            opt(cs[tim].pos);
            swap(c[cs[tim].pos], cs[tim].val);
            opt(cs[tim].pos);
        }
        else swap(c[cs[tim].pos], cs[tim].val);
    }
    int main() {
        n = read(), m = read(), nq = read();
        sz = (int)pow(n, 0.6666666666666);
        rep(i, 1, m) v[i] = read(); rep(i, 1, n) w[i] = read();
        rep(i, 2, n) {
            int u = read(), v = read();
            add(u, v); add(v, u);
        }sp_dfs1(1); sp_dfs2(1, 1); fk_dfs(1);
        rep(i, 1, n) c[i] = read();
        rep(i, 1, nq) {
            int opt = read(), x = read(), y = read();
            if(opt == 0) cs[++ccnt] = Chg(x, y);
            if(opt == 1) {
                if(bl[x] > bl[y]) swap(x, y);
                qs[++qcnt] = Ques(x, y, bl[x], bl[y], qcnt, ccnt);
            }
        }
        sort(qs + 1, qs + qcnt + 1);
        while(tp) bl[q[--tp]] = bcnt;
        //rep(i, 1, n) cout << bl[i] << " ";
        //cout << endl;
        int cu = 1, cv = 1;
        //return 0;
        rep(i, 1, qcnt) {
            //cout << iter << " " << qs[i].t << endl;
            while(iter < qs[i].t) change(++iter);
            while(iter > qs[i].t) change(iter--);
            int qu = qs[i].u, qv = qs[i].v;
            int anc = lca(cu, qu);
            while(cu != anc) move(cu); while(qu != anc) move(qu);
            anc = lca(cv, qv);
            while(cv != anc) move(cv); while(qv != anc) move(qv);
            cu = qs[i].u, cv = qs[i].v;
            anc = lca(cu, cv);
            opt(anc); ans[qs[i].id] = now; opt(anc);
            //cout << i << " " << qs[i].id << endl;
        }
        rep(i, 1, qcnt) printf("%lld
    ", ans[i]);
    }
    /*
    4 3 5
    1 9 2
    7 6 5 1
    2 3
    3 1
    3 4
    1 2 3 2
    1 1 2
    1 4 2
    0 2 1
    1 1 2
    1 4 2
    */
    View Code
  • 相关阅读:
    javascript 犀牛书
    Hmtl/css
    SQL Server 查询中使用Union或Union All后Order by排序无效(嵌套查询乱序)
    CSS 动画
    CSS 文字排版
    CSS 太极图
    Amazon Products 服务费估算
    CSS3 结构伪类选择器
    JS 执行机制
    vue 生命周期函数的学习
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10500675.html
Copyright © 2020-2023  润新知