zoukankan      html  css  js  c++  java
  • 2590 树的统计

    看到lct的题解比较少,所以我来贡献一篇

    注意的地方and坑点

    1. 只用把mmax [ 0 ](维护的最大值)初始化为极小值

    2. sum [ i ] , mmax [ i ]在输入时就可赋值为val [ i ]

    3. 要先储存下联通的点,在输入完val后再进行link操作

    CHANGE操作

    change ( x , v )表示把 val [ x ] 改成v

    步骤:

    1. 将x点splay到根

    2. 更新 val [ x ] = v

    3. 进行pushup(x)操作

    QMAX and QSUM操作

    输入x,y表示询问x,y路径上的最大权值或者路径和

    步骤

    1. 只需split ( x , y ),然后输出 mmax [ y ] 或者 sum [ y ] 即可

    2. 此时 mmax [ y ] 或 sum [ y ] 表示的就是x到y这条链上的最大权值 或者 权值和了

    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define MN 4000001
    #define re register int
    #define ll long long
    #define inf 0x7fffffff
    using namespace std;
    int f[MN], val[MN], sum[MN], r[MN], son[MN][2];
    int mmax[MN], size[MN];
    int fake1[MN], fake2[MN];
    int zhan[MN];
    int n, m, cnt;
    int get(int x) {  ////判断节点是否为一个Splay的根(与普通Splay的区别1)
        return son[f[x]][0] == x || son[f[x]][1] == x;
    }  ////如果连的是轻边,他的父亲的儿子里没有它
    void pushup(int x) {
        sum[x] = sum[son[x][0]] + sum[son[x][1]] + val[x];
        mmax[x] = max(max(mmax[son[x][0]], mmax[son[x][1]]), val[x]);
    }
    void filp(int x) {
        swap(son[x][0], son[x][1]);
        r[x] ^= 1;
    }
    void pushdown(int x) {
        if (!r[x])
            return;
        r[x] = 0;
        if (son[x][0])
            filp(son[x][0]);
        if (son[x][1])
            filp(son[x][1]);
    }
    void rotate(int x) {
        int y = f[x], z = f[y], k = (son[y][1] == x), s = son[x][!k];
        if (get(y))
            son[z][son[z][1] == y] = x;
        son[x][!k] = y;
        son[y][k] = s;
        if (s)
            f[s] = y;
        f[y] = x;
        f[x] = z;
        pushup(y);
        // pushup(x);
    }
    void splay(int x) {
        int y = x, top = 0;
        zhan[++top] = y;
        while (get(y)) zhan[++top] = f[y], y = f[y];
        while (top) pushdown(zhan[top--]);
        while (get(x)) {
            y = f[x], top = f[y];
            if (get(y))
                rotate((son[y][0] == x) ^ (son[top][0] == y) ? x : y);
            rotate(x);
        }
        pushup(x);
        return;
    }
    void access(int x) {
        for (re y = 0; x; y = x, x = f[x]) {
            splay(x);
            son[x][1] = y;
            pushup(x);
        }
    }
    void makeroot(int x) {
        access(x);
        splay(x);
        filp(x);
    }
    int findroot(int x) {
        access(x);
        splay(x);
        while (son[x][0]) pushdown(x), x = son[x][0];
        splay(x);
        return x;
    }
    void split(int x, int y) {
        makeroot(x);
        access(y);
        splay(y);
    }
    void cut(int x, int y) {
        split(x, y);
        if (findroot(y) == x && f[y] == x && !son[y][0]) {
            f[y] = son[x][1] = 0;
            pushup(x);
        }
        return;
    }
    void link(int x, int y) {
        makeroot(x);
        if (findroot(y) != x)
            f[x] = y;
    }
    void change(int x, int v) {
        splay(x);
        val[x] = v;
        pushup(x);
    }
    int main() {
        mmax[0] = -inf;
        scanf("%d", &n);
        for (re i = 1; i <= n - 1; i++) {
            scanf("%d%d", &fake1[i], &fake2[i]);
        }  //先储存下要link的点,等输入完val后再操作
        //巨坑
        for (re i = 1; i <= n; i++) {
            scanf("%d", &val[i]);
            sum[i] = mmax[i] = val[i];
        }
        int t;
        for (re i = 1; i <= n - 1; i++) link(fake1[i], fake2[i]);
        scanf("%d", &t);
        for (re i = 1; i <= t; i++) {
            char s[7];
            int a1, a2;
            scanf("%s", s);
            scanf("%d%d", &a1, &a2);
            if (s[0] == 'C') {
                change(a1, a2);
            }
            if (s[0] == 'Q' && s[1] == 'M') {
                split(a1, a2);
                printf("%d
    ", mmax[a2]);
            }
            if (s[0] == 'Q' && s[1] == 'S') {
                split(a1, a2);
                printf("%d
    ", sum[a2]);
            }
        }
        // for(re i=1;i<=n;i++)
        // printf("%d %d
    ",mmax[i],sum[i]);
    
        return 0;
    }
    缘分让我们相遇乱世以外, 命运却要我们危难中相爱。 也许未来遥远在光年之外, 我愿守候未知里为你等待。
  • 相关阅读:
    HiLink & LiteOS & IoT芯片 让IoT开发简单高效
    HiCar基本功能介绍
    HiCar技术概述
    docker 笔记 3
    drools规则引擎笔记 与 代码demo
    Spring Reactive Reactor WebFlux Flux Mono 是否能完全取代多线程编程 ?
    webflux demo 1
    阅后归档
    阅后归档
    POJ3252 Round Numbers(数位dp)
  • 原文地址:https://www.cnblogs.com/zw130-lzr-blogs/p/11220329.html
Copyright © 2011-2022 走看看