• 树链剖分练习题


    树链剖分练习题

    洛谷补题链接

    P3038 USACO11DEC]Grass Planting G

    /*
    2020/8/17/8:34
    树链剖分:含点权转边权处理。
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    const ll mod = 1e9 + 7;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    
    
    int n, m, r;
    int head[N], cnt = 0;
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    struct Tree{
        int l, r, val, lz;
    }tree[N * 4];
    int val[N], tval[N];
    int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
    int res = 0, tot = 0;
    
    void add(int u, int v){
        edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    void pushdown(int index){
        if(tree[index].lz){
            tree[index << 1].val += (tree[index << 1].r - tree[index << 1].l + 1) * tree[index].lz;
            tree[index << 1 | 1].val += (tree[index<<1|1].r - tree[index<<1|1].l + 1) * tree[index].lz;
            tree[index << 1].lz += tree[index].lz;
            tree[index << 1 | 1].lz += tree[index].lz;
            tree[index].lz = 0;
        }
    }
    
    void pushup(int index){
        tree[index].val = (tree[index << 1].val + tree[index << 1 | 1].val);
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l, tree[index].r = r;
        tree[index].lz = 0;
        if(l == r){
            tree[index].val = 0;
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata(int l, int r, int index, int val){
        if(tree[index].l >= l && tree[index].r <= r){
            tree[index].lz += val;
            tree[index].val += (tree[index].r - tree[index].l + 1) * val;
            return;
        }
        if(tree[index].lz) pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata(l, r, index << 1, val);
        if(r > mid) updata(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    int query(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].val;
        }
        if(tree[index].lz) pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        int ans = 0;
        if(l <= mid) ans += query(l, r, index << 1);
        if(r > mid) ans += query(l, r, index << 1 | 1);
        return ans;
    }
    // --------------------------------
    
    int qRange(int x, int y){ //x 到 y树上最短路径结点权值和
        int res = 0;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            res += query(dfn[top[x]], dfn[x], 1);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        res += query(dfn[x] + 1, dfn[y], 1);
        return res;
    }
    
    void updRange(int x, int y, int c){ //x 到 y最短路径上点值 + z
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            updata(dfn[top[x]], dfn[x], 1, c);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        updata(dfn[x] + 1, dfn[y], 1, c);
    }
    
    
    int qSon(int x){ //以x为根结点的子树内所有节点值之和
        return query(dfn[x], dfn[x] + siz[x] - 1, 1);
    }
    
    
    void updSon(int x, int val){ //以x为根的子树内所有节点值 + z
        updata(dfn[x], dfn[x] + siz[x] - 1, 1, val);
    }
    
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        fa[u] = pre;
        siz[u] = 1;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == pre) continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){ //topu当前链的最顶端的节点
        dfn[u] = ++ tot;
        tval[tot] = val[u];
        top[u] = topu;
        rnk[tot] = u;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == son[u] || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    
    
    //树链剖分求LCA
    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]) return x;
        else return y;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        cnt = 0;
        for(int i = 0; i <= n; ++ i) head[i] = -1;
        for(int i = 1; i < n; ++ i){
            int x, y; scanf("%d%d",&x,&y);
            add(x, y);
        }
        
        dfs1(1, 1);
        dfs2(1, 1);
        Build(1, n, 1);
        char s[5];
        while(m --){
            int x, y; scanf("%s%d%d",s,&x,&y);
            if(s[0] == 'P'){
                updRange(x, y, 1);
            }
            else{
                printf("%d
    ",qRange(x, y));
            }
        }
        return 0;
    }
    

    P3128 USACO15DEC]Max Flow P

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<cmath>
    
    using namespace std;
    typedef long long ll;
    const int MA=5e4+5;
    
    int n,cnt=0,t,k,ans;
    int head[MA],f[MA][30],d[MA],txt[MA],fa[MA];
    struct node
    {
        int to;
        int next;
    }edge[MA*3];
    queue<int>q;
    
    
    inline void add(int u,int v)
    {
        edge[++cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt;
    }
    
    
    void bfs()
    {
        q.push(1);
        d[1]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i;i=edge[i].next){
                int v=edge[i].to;
                if(d[v])continue;
                fa[v]=u;
                d[v]=d[u]+1;
                f[v][0]=u;
                for(int j=1;j<=t;++j)
                    f[v][j]=f[f[v][j-1]][j-1];
                q.push(v);
            }
        }
    }
    
    void dfs(int u,int pre)
    {
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;
            if(v==pre)continue;
            dfs(v,u);
            txt[u]+=txt[v];
            ans=max(ans,txt[u]);
        }
    }
    
    int LCA(int x,int y)
    {
        if(d[x]>d[y])swap(x,y);
        for(int i=t;i>=0;--i)
            if(d[f[y][i]]>=d[x])y=f[y][i];
        if(x==y)return x;
        for(int i=t;i>=0;--i)
            if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    
    int main()
    {
        scanf("%d%d",&n,&k);
        t=(int)(log(n)/log(2))+1;
        for(int i=1;i<n;++i){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        bfs();
        for(int i=1;i<=k;++i){
            int x,y;
            scanf("%d%d",&x,&y);
            txt[x]+=1;
            txt[y]+=1;
            txt[LCA(x,y)]-=1;
            txt[fa[LCA(x,y)]]-=1;
        }
        ans=0;
        dfs(1,0);
        printf("%d
    ",ans);
        return 0;
    }
    

    P4427 BJOI2018]求和

    /*
    P4427 
    
    2020/8/17/11:02
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 4e5+ 5;
    const ll mod = 998244353;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    inline int read(){
        register int ans=0;register char c=getchar();register bool neg=0;
        while((c<'0')|(c>'9')) neg^=!(c^'-'),c=getchar();
        while((c>='0')&(c<='9')) ans=(ans<<3)+(ans<<1)+c-'0',c=getchar();
        return neg?-ans:ans;
    }
    inline void write(int x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x>9) write(x/10);
        putchar(x%10+'0');
    }
    
    
    int n, m, k;
    int head[N], cnt = 0;
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    struct Tree{
        int l, r; ll val, lz;
    }tree[N * 4];
    int tval[N];
    int son[N], siz[N],dfn[N], dep[N], top[N], fa[N];
    ll sol[N][60];
    int tot = 0;
    
    void add(int u, int v){
        edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        fa[u] = pre;
        siz[u] = 1;
        int maxx = -1;
        
        for(int i = 0; i <= 50; ++ i){
            sol[u][i] = sol[pre][i] + qpow(dep[u], i);
            sol[u][i] %= mod;
        }
        
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == pre) continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
        
    }
    
    void dfs2(int u, int topu){ //topu当前链的最顶端的节点
        dfn[u] = ++ tot;
        tval[tot] = dep[u];
        top[u] = topu;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == son[u] || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    //树链剖分求LCA
    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]) return x;
        else return y;
    }
    
    void tree_cut(){
       dep[0] = -1;
       dfs1(1, 0);
       dfs2(1, 1);   
    }
    
    int main()
    {
        n = read();
        cnt = 0;
        for(int i = 0; i <= n; ++ i) head[i] = -1;
        for(int i = 1; i < n; ++ i){
            int x, y; x = read(); y = read();
            add(x, y);
        }
        tree_cut();
        m = read();
        while(m --){
            int x, y; x = read(); y = read(); k = read();
            int lca = LCA(x, y);
            ll res = (sol[x][k] + sol[y][k]) % mod;
            res = ((res - sol[fa[lca]][k] + mod) % mod - sol[lca][k] + mod) % mod;
            write(res);
            puts("");
        }
        return 0;
    }
    

    P6098 USACO19FEB]Cow Land G

    /*
    2020/8/17/12:04
    
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    const ll mod = 1e9 + 7;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    
    // int tpp[N];
    
    int n, m, r;
    int head[N], cnt = 0;
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    struct Tree{
        int l, r, val, lz;
    }tree[N * 4];
    int val[N], tval[N];
    int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
    int res = 0, tot = 0;
    
    void add(int u, int v){
        edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    
    void pushup(int index){
        tree[index].val = (tree[index << 1].val ^ tree[index << 1 | 1].val);
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l, tree[index].r = r;
        tree[index].lz = 0;
        if(l == r){
            // tpp[l] = index;
            tree[index].val = tval[l];
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata(int l, int r, int index, int val){
        if(tree[index].l == tree[index].r){
            tree[index].val = val;
            return;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata(l, r, index << 1, val);
        if(r > mid) updata(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    int query(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].val;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        int ans = 0;
        if(l <= mid) ans ^= query(l, r, index << 1);
        if(r > mid) ans ^= query(l, r, index << 1 | 1);
        return ans;
    }
    // --------------------------------
    
    int qRange(int x, int y){ //x 到 y树上最短路径结点权值和
        int res = 0;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            res ^= query(dfn[top[x]], dfn[x], 1);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        res ^= query(dfn[x], dfn[y], 1);
        return res;
    }
    
    void updRange(int x, int y, int c){ //x 到 y最短路径上点值 + z
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            updata(dfn[top[x]], dfn[x], 1, c);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        updata(dfn[x], dfn[y], 1, c);
    }
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        fa[u] = pre;
        siz[u] = 1;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == pre) continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){ //topu当前链的最顶端的节点
        dfn[u] = ++ tot;
        tval[tot] = val[u];
        top[u] = topu;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == son[u] || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        cnt = 0;
        for(int i = 0; i <= n ; ++ i) head[i] = -1;
        for(int i = 1; i <= n; ++ i) scanf("%d",&val[i]);
        for(int i = 1; i < n; ++ i){
            int x, y; scanf("%d%d",&x,&y);
            add(x, y);
        }
        dfs1(1, 1);
        dfs2(1, 1);
        Build(1, n, 1);
        while(m --){
            int op, x, y;
            scanf("%d%d%d",&op,&x,&y);
            if(op == 1){
                updRange(x, x, y);
            }
            else{
                printf("%d
    ",qRange(x, y));
            }
    
            // for(int i = 1; i <= n; ++ i){
                // cout<<tree[tpp[i]].val<<" ";
            // }
            // cout<<endl;
        }
        return 0;
    }
    

    P4092 HEOI2016/TJOI2016]树

    /*
    2020/8/17/13:04
    
    */
    
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    const ll mod = 1e9 + 7;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    
    
    int n, m, r;
    int head[N], cnt = 0;
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    struct Tree{
        int l, r, val, lz;
    }tree[N * 4];
    int val[N], tval[N];
    int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
    int res = 0, tot = 0;
    
    void add(int u, int v){
        edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    void pushup(int index){
        tree[index].val = max(tree[index << 1].val , tree[index << 1 | 1].val);
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l, tree[index].r = r;
        tree[index].lz = 0;
        if(l == r){
            tree[index].val = 0;
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata(int l, int r, int index, int val){
        if(tree[index].l >= l && tree[index].r <= r){
            tree[index].val = val;
            return;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata(l, r, index << 1, val);
        if(r > mid) updata(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    int query(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].val;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        int ans = 0;
        if(r > mid) ans = query(l, r, index << 1 | 1);
        if(l <= mid) ans = max(ans, query(l, r, index << 1));
        return ans;
    }
    // --------------------------------
    
    int qRange(int x, int y){ //x 到 y树上最短路径结点权值和
        int res = 0;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            int tt = query(dfn[top[x]], dfn[x], 1);
            if(tt != 0) return tt;
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        return query(dfn[x], dfn[y], 1);
    }
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        fa[u] = pre;
        siz[u] = 1;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == pre) continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){ //topu当前链的最顶端的节点
        dfn[u] = ++ tot;
        top[u] = topu;
        rnk[tot] = u;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == son[u] || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        cnt = 0;
        for(int i = 0; i <= n; ++ i) head[i] = -1;
        for(int i = 1; i < n; ++ i){
            int x, y; scanf("%d%d",&x,&y);
            add(x, y);
        }
        dfs1(1, 0);
        dfs2(1, 1);
        Build(1, n, 1);
        updata(dfn[1], dfn[1], 1, 1);
        char op[5];
        while(m --){
            int x; scanf("%s%d",op,&x);
            if(op[0] == 'C'){
                updata(dfn[x], dfn[x], 1, dfn[x]);
            }
            else{
                printf("%d
    ",rnk[qRange(1, x)]);
            }
        }
    }
    

    P4315 月下“毛景树”

    /*
    2020/8/17/19:59
    树链剖分:含点权转边权处理。
    区间加
    区间覆盖
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    const ll mod = 1e9 + 7;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    int tpp[N];
    
    int n, m;
    
    int ax[N], ay[N];
    int head[N], cnt = 0, tot = 0;
    int siz[N], dep[N], fa[N], son[N];
    int dfn[N], tval[N], val[N], top[N], rnk[N];
    
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    void add(int u, int v, int w){
        edge[cnt].to = v, edge[cnt].c = w, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].c = w, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    struct Tree{
        int l, r, val;
        int lz1, lz2;
    }tree[N * 4];
    
    void pushdown(int index){
        if(tree[index].lz1 >= 0){
            tree[index << 1].val = tree[index << 1 | 1].val = tree[index].lz1;
            tree[index << 1].lz1 = tree[index << 1 | 1].lz1 = tree[index].lz1;
            tree[index << 1].lz2 = tree[index << 1 | 1].lz2 = 0;
            tree[index].lz1 = -1;
        }
        
        if(tree[index].lz2){
            tree[index << 1].val += tree[index].lz2; tree[index << 1 | 1].val += tree[index].lz2;
            tree[index << 1].lz2 += tree[index].lz2; tree[index << 1 | 1].lz2 += tree[index].lz2;
            tree[index].lz2  = 0;
        }
    }
    
    void pushup(int index){
        tree[index].val = max(tree[index << 1].val, tree[index << 1 | 1].val);
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l; tree[index].r = r;
        tree[index].lz1 = -1; tree[index].lz2 = tree[index].val = 0;
        if(l == r){
            // tpp[l] = index;
            tree[index].val = tval[l];
            return;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata1(int l, int r, int index, int val){ 
        if(tree[index].l >= l && tree[index].r <= r){
            tree[index].lz1 = val;
            tree[index].lz2 = 0;
            tree[index].val = val;
            return;
        }
        pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata1(l, r, index << 1, val);
        if(r > mid) updata1(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    void updata2(int l, int r, int index, int val){
        if(tree[index].l >= l && tree[index].r <= r){
            tree[index].lz2 += val;
            tree[index].val += val;
            return;
        }
        pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata2(l, r, index << 1, val);
        if(r > mid) updata2(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    int query(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].val;
        }
        pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        int res = 0;
        if(l <= mid) res = max(res, query(l, r, index << 1));
        if(r > mid) res = max(res, query(l, r, index << 1 | 1));
        return res;
    }
    
    //--------------------------
    void Change(int x, int val){
        updata1(dfn[x], dfn[x], 1, val);
    }
    
    void Cover(int x, int y, int val){
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            updata1(dfn[top[x]], dfn[x], 1, val);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        updata1(dfn[x] + 1, dfn[y], 1, val);
    }
    
    void Add(int x, int y, int val){
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            updata2(dfn[top[x]], dfn[x], 1, val);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        updata2(dfn[x] + 1, dfn[y], 1, val);
    }
    
    int Max(int x, int y){
        int ans = 0;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            ans = max(ans, query(dfn[top[x]], dfn[x], 1));
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        ans = max(ans, query(dfn[x] + 1, dfn[y], 1));
        return ans;
    }
    
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        siz[u] = 1;
        fa[u] = pre;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to, w = edge[i].c;
            if(v == pre) continue;
            val[v] = w;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){
        dfn[u] = ++ tot;
        tval[tot] = val[u];
        top[u] = topu;
        rnk[tot] = u;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to, w = edge[i].c;
            if(v == son[u] || v == fa[u]) continue;
            
            dfs2(v, v);
        }
    }
    
    // void print(){
        // for(int i = 1; i <= n; ++ i){
            // int tt = tpp[dfn[i]];
            // cout<<tree[tt].val<<" ";
        // }
        // cout<<endl;
    // }
    
    int main()
    {
        scanf("%d",&n);
        cnt = 0;
        for(int i = 0; i <= n; ++ i) head[i] = -1;
        for(int i = 1; i < n; ++ i){
            int z; scanf("%d%d%d",&ax[i], &ay[i], &z);
            add(ax[i], ay[i], z);
        }
        
        dfs1(1, 0);
        dfs2(1, 1);
        Build(1, n, 1);
        
        // print();
        
        char op[10];
        while(1){
            scanf("%s",op);
            if(op[0] == 'S') break;
            else if(op[1] == 'h'){  //change
                int x, y; scanf("%d%d",&x,&y);
                if(dep[ax[x]] < dep[ay[x]]) Change(ay[x], y);
                else Change(ax[x], y);
            }
            else if(op[1] == 'o'){ //Cover
                int x, y, z; scanf("%d%d%d",&x,&y,&z);
                Cover(x, y, z);
            }
            else if(op[1] == 'd'){   //Add
                int x, y, z; scanf("%d%d%d",&x,&y,&z);
                Add(x, y, z);
            }
            else{
                int x, y; scanf("%d%d",&x,&y);
                printf("%d
    ",Max(x, y));
            }
            // print();
        }
        return 0;
    }
    
    
    //
    
    // 8
    // 1 2 1
    // 2 3 2
    // 3 4 1
    // 3 7 3
    // 4 5 4
    // 4 8 2
    // 5 6 2
    // Max 1 2
    // Max 2 7
    // Cover 1 7 6
    // Max 1 7
    // Max 2 7
    // Add 2 7 2
    // Max 1 7
    // Max 2 7
    // Cover 1 6 1
    
    

    P2590 ZJOI2008]树的统计

    /*
    2020/8/17/19:59
    树链剖分:区间最值 + 区间和
    线段树维护两个值
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    const ll mod = 1e9 + 7;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    int tpp[N];
    
    int n, m;
    
    int ax[N], ay[N];
    int head[N], cnt = 0, tot = 0;
    int siz[N], dep[N], fa[N], son[N];
    int dfn[N], tval[N], val[N], top[N], rnk[N];
    
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    void add(int u, int v){
        edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    struct Tree{
        int l, r, maxx, sum;
    }tree[N * 4];
    
    
    void pushup(int index){
        tree[index].maxx = max(tree[index << 1].maxx, tree[index << 1 | 1].maxx);
        tree[index].sum = tree[index << 1].sum + tree[index << 1 | 1].sum; 
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l; tree[index].r = r;
        tree[index].maxx = -INF; tree[index].maxx = 0;
        if(l == r){
            // tpp[l] = index;
            tree[index].maxx = tval[l];
            tree[index].sum = tval[l];
            return;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata(int l, int r, int index, int val){ 
        if(tree[index].l == tree[index].r){
            tree[index].maxx = tree[index].sum = val;
            return;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata(l, r, index << 1, val);
        if(r > mid) updata(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    
    int queryMax(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].maxx;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        int res = -INF;
        if(l <= mid) res = max(res, queryMax(l, r, index << 1));
        if(r > mid) res = max(res, queryMax(l, r, index << 1 | 1));
        return res;
    }
    
    int querySum(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].sum;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        int res = 0;
        if(l <= mid) res += querySum(l, r, index << 1);
        if(r > mid) res += querySum(l, r, index << 1 | 1);
        return res;
    }
    
    //-------------------------------
    
    void Change(int x, int val){
        updata(dfn[x], dfn[x], 1, val);
    }
    
    int Sum(int x, int y){
        int ans = 0;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            ans += querySum(dfn[top[x]], dfn[x], 1);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x ,y);
        ans += querySum(dfn[x], dfn[y], 1);
        return ans;
    }
    
    int Max(int x, int y){
        int ans = -INF;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            ans = max(ans, queryMax(dfn[top[x]], dfn[x], 1));
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        ans = max(ans, queryMax(dfn[x], dfn[y], 1));
        return ans;
    }
    
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        siz[u] = 1;
        fa[u] = pre;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to, w = edge[i].c;
            if(v == pre) continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){
        dfn[u] = ++ tot;
        tval[tot] = val[u];
        top[u] = topu;
        rnk[tot] = u;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to, w = edge[i].c;
            if(v == son[u] || v == fa[u]) continue;
            
            dfs2(v, v);
        }
    }
    
    // void print(){
        // for(int i = 1; i <= n; ++ i){
            // int tt = tpp[dfn[i]];
            // cout<<tree[tt].maxx<<" ";
        // }
        // cout<<endl;
    // }
    
    
    int main()
    {
        scanf("%d",&n);
        cnt = 0;
        for(int i = 0; i <= n; ++ i) head[i] = -1;
        for(int i = 1; i < n; ++ i){
            int x, y; scanf("%d%d",&x,&y);
            add(x, y);
        }
        for(int i = 1; i <= n; ++ i) scanf("%d",&val[i]);
        
        dfs1(1, 0);
        dfs2(1, 1);
        Build(1, n, 1);
        // print();
        scanf("%d",&m);
        char op[10];
        while(m --){
            scanf("%s",op);
            if(op[0] == 'C'){
                int x, y; scanf("%d%d",&x,&y);
                Change(x, y);
            }
            else if(op[1] == 'M'){ 
                int x, y; scanf("%d%d",&x,&y);
                printf("%d
    ",Max(x, y));
            }
            else if(op[1] == 'S'){
                int x, y; scanf("%d%d",&x,&y);
                printf("%d
    ",Sum(x, y));
            }
            // print();
        }
        return 0;
    }
    
    

    P3833 SHOI2012]魔法树

    /*
    2020/8/17/21:35
    
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    const ll mod = 1e9 + 7;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    int tpp[N];
    
    int n, m;
    
    int ax[N], ay[N];
    int head[N], cnt = 0, tot = 0;
    int siz[N], dep[N], fa[N], son[N];
    int dfn[N], tval[N], val[N], top[N], rnk[N];
    
    struct node{
        int to, nxt;
    }edge[N << 1];
    
    void add(int u, int v){
        edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    struct Tree{
        int l, r; ll val, lz;
    }tree[N * 4];
    
    void pushdown(int index){
        if(tree[index].lz){
            tree[index << 1].val += (tree[index << 1].r - tree[index << 1].l + 1) * tree[index].lz;
            tree[index << 1 | 1].val += (tree[index << 1 | 1].r - tree[index << 1 | 1].l + 1) * tree[index].lz;
            tree[index << 1].lz += tree[index].lz;
            tree[index << 1 | 1].lz += tree[index].lz;
            tree[index].lz = 0;
        }
    }
    
    void pushup(int index){
        tree[index].val = tree[index << 1].val + tree[index << 1 | 1].val;
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l; tree[index].r = r;
        tree[index].val = 0;
        if(l == r){
            // tpp[l] = index;
            return;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata(int l, int r, int index, ll val){
        if(tree[index].l >= l && tree[index].r <= r){
            tree[index].lz += val;
            tree[index].val += (tree[index].r - tree[index].l + 1) * val;
            return;
        }
        pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata(l, r, index << 1, val);
        if(r > mid) updata(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    ll query(int l, int r, int index){
        if(tree[index].l >= l && tree[index].r <= r){
            return tree[index].val;
        }
        pushdown(index);
        ll ans = 0;
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) ans += query(l, r, index << 1);
        if(r > mid) ans += query(l, r, index << 1 | 1);
        return ans;
    }
    
    //-------------------------------
    
    void Asol(int x, int y, int val){
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            updata(dfn[top[x]], dfn[x], 1, val);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        updata(dfn[x], dfn[y], 1, val);
    }
    
    ll Qsol(int x){
        return query(dfn[x], dfn[x] + siz[x] - 1, 1);
    }
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        siz[u] = 1;
        fa[u] = pre;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == pre) continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){
        dfn[u] = ++ tot;
        top[u] = topu;
        rnk[tot] = u;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == son[u] || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    // void print(){
        // for(int i = 1; i <= n; ++ i){
            // int tt = tpp[dfn[i]];
            // cout<<tree[tt].maxx<<" ";
        // }
        // cout<<endl;
    // }
    
    
    int main()
    {
        scanf("%d",&n);
        cnt = 0;
        for(int i = 0; i <= n; ++ i) head[i] = -1;
        for(int i = 1; i < n; ++ i){
            int x, y; scanf("%d%d",&x,&y);
            add(x + 1, y + 1);
        }
        dfs1(1, 0);
        dfs2(1, 1);
        Build(1 , n, 1);
        scanf("%d",&m);
        char op[10];
        while(m --){
            scanf("%s",op);
            if(op[0] == 'A'){
                int x, y; ll z; scanf("%d%d%lld",&x,&y,&z);
                x ++; y ++;
                Asol(x, y, z);
            }
            else if(op[0] == 'Q'){
                int x; scanf("%d",&x);
                x ++;
                printf("%lld
    ",Qsol(x));
            }
        }
        return 0;
    }
    

    P2146 NOI2015]软件包管理器

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    const ll mod = 1e9 + 7;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    
    // int tpp[N];
    
    int n, m, r;
    int head[N], cnt = 0;
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    struct Tree{
        int l, r, val, lz;
    }tree[N * 4];
    int val[N], tval[N];
    int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
    int res = 0, tot = 0;
    
    void add(int u, int v){
        edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    void pushdown(int index){
        tree[index << 1].val = (tree[index << 1].r - tree[index << 1].l + 1) * tree[index].lz;
        tree[index << 1 | 1].val = (tree[index<<1|1].r - tree[index<<1|1].l + 1) * tree[index].lz;
        tree[index << 1].lz = tree[index].lz;
        tree[index << 1 | 1].lz = tree[index].lz;
        tree[index].lz = -1;
    }
    
    void pushup(int index){
        tree[index].val = (tree[index << 1].val + tree[index << 1 | 1].val);
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l, tree[index].r = r;
        tree[index].lz = -1;
        if(l == r){
            // tpp[l] = index;
            tree[index].val = 0;
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata(int l, int r, int index, int val){
        
        if(tree[index].l >= l && tree[index].r <= r){
            tree[index].lz = val;
            tree[index].val = (tree[index].r - tree[index].l + 1) * val;
            return;
        }
        if(tree[index].lz != -1) pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata(l, r, index << 1, val);
        if(r > mid) updata(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    int query(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].val;
        }
        if(tree[index].lz != -1) pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        int ans = 0;
        if(l <= mid) ans += query(l, r, index << 1);
        if(r > mid) ans += query(l, r, index << 1 | 1);
        return ans;
    }
    // --------------------------------
    
    int qRange(int x, int y){ //x 到 y树上最短路径结点权值和
        int res = 0;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            res += query(dfn[top[x]], dfn[x], 1);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        res += query(dfn[x], dfn[y], 1);
        return res % mod;
    }
    
    void updRange(int x, int y, int c){ //x 到 y最短路径上点值 + z
        c %= mod;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            updata(dfn[top[x]], dfn[x], 1, c);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        updata(dfn[x], dfn[y], 1, c);
    }
    
    
    int qSon(int x){ //以x为根结点的子树内所有节点值之和
        return query(dfn[x], dfn[x] + siz[x] - 1, 1);
    }
    
    
    void updSon(int x, int val){ //以x为根的子树内所有节点值 + z
        updata(dfn[x], dfn[x] + siz[x] - 1, 1, val);
    }
    
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        fa[u] = pre;
        siz[u] = 1;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == pre) continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){ //topu当前链的最顶端的节点
        dfn[u] = ++ tot;
        tval[tot] = val[u];
        top[u] = topu;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == son[u] || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    int main()
    {
        scanf("%d",&n);
        cnt = 0;
        for(int i = 0; i <= n ; ++ i) head[i] = -1;
        for(int i = 2; i <= n; ++ i){
            int x; scanf("%d",&x);
            add(x + 1, i);
        }
        dfs1(1, 1);
        dfs2(1, 1);
        Build(1, n, 1);
        int q; scanf("%d",&q);
        char s[20];
        while(q --){
            int x;
            scanf("%s",s); 
            scanf("%d",&x); x += 1;
            
            if(s[0] == 'i'){
                int temp = qRange(1, x);
                updRange(1, x, 1);
                int res = qRange(1, x) - temp;
                printf("%d
    ",res);
            }
            else{
                int res = qSon(x);
                updSon(x, 0);
                printf("%d
    ",res);
            }
            // for(int i = 1; i <= n; ++ i){
                // cout<<tree[tpp[i]].val<<" ";
            // }
            // cout<<endl;
        }
        return 0;
    }
    

    P3178 HAOI2015]树上操作

    /*
    2020/8/19/8:40
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    // const ll mod = 1e9 + 7;
    int mod;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    
    int tpp[N];
    
    int n, m, r;
    int head[N], cnt = 0;
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    struct Tree{
        int l, r; ll val, lz;
    }tree[N * 4];
    int val[N], tval[N];
    int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
    int res = 0, tot = 0;
    
    void add(int u, int v){
        edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    void pushdown(int index){
        if(tree[index].lz){
            ll temp = tree[index].lz;
            tree[index].lz = 0;
            tree[index << 1].val += (tree[index << 1].r - tree[index << 1].l + 1) * temp;
            tree[index << 1 | 1].val += (tree[index<<1|1].r - tree[index<<1|1].l + 1) * temp;
            tree[index << 1].lz += temp;
            tree[index << 1 | 1].lz += temp;
        }
    }
    
    void pushup(int index){
        tree[index].val = tree[index << 1].val + tree[index << 1 | 1].val;
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l, tree[index].r = r;
        tree[index].lz = 0;
        if(l == r){
            tree[index].val = tval[l];
            tpp[l] = index;
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata(int l, int r, int index, int val){
        if(tree[index].l >= l && tree[index].r <= r){
            tree[index].lz += val;
            tree[index].val += (ll)val * (tree[index].r - tree[index].l + 1);
            return;
        }
        pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata(l, r, index << 1, val);
        if(r > mid) updata(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    ll query(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].val;
        }
        pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        ll ans = 0;
        if(l <= mid) ans += query(l, r, index << 1);
        if(r > mid) ans += query(l, r, index << 1 | 1);
        return ans;
    }
    
    // --------------------------------
    
    void Change(int x, int val){
        updata(dfn[x], dfn[x], 1, val);
    }
    
    void Add(int x, int val){
        updata(dfn[x], dfn[x] + siz[x] - 1, 1, val);
    }
    
    ll Qsol(int x, int y){
        ll ans = 0;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            ans += query(dfn[top[x]], dfn[x], 1);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        ans += query(dfn[x], dfn[y], 1);
        return ans;
    }
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        fa[u] = pre;
        siz[u] = 1;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == pre) continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){ //topu当前链的最顶端的节点
        dfn[u] = ++ tot;
        tval[tot] = val[u];
        top[u] = topu;
        rnk[tot] = u;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == son[u] || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    // void print(){
        // for(int i = 1; i <= n; ++ i){
            // int tt = tpp[dfn[i]];
            // cout<<tree[tt].val<<" ";
        // }
        // cout<<endl;
    // }
    
    
    int main()
    {
        scanf("%d%d",&n,&m);
        cnt = 0;
        for(int i = 0; i <= n; ++ i) head[i] = -1;
        for(int i = 1; i <= n; ++ i) scanf("%d",&val[i]);
        for(int i = 1; i < n; ++ i){
            int x, y; scanf("%d%d",&x,&y);
            add(x, y);
        }
        dfs1(1, 0);
        dfs2(1, 1);
        Build(1, n, 1);
        
        // print();
        
        int op;
        while(m --){
            scanf("%d",&op);
            if(op == 1){
                int x, y; scanf("%d%d",&x,&y);
                Change(x, y);
            }
            else if(op == 2){
                int x, y; scanf("%d%d",&x,&y);
                Add(x, y);
            }
            else{
                int x; scanf("%d",&x);
                printf("%lld
    ",Qsol(x, 1));
            }
            
            // print();
        }
        return 0;
    }
    

    P3950 部落冲突

    /*
    P3950
    树链剖分
    2020/8/19/9:15
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    // const ll mod = 1e9 + 7;
    int mod;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    
    // int tpp[N];
    
    int n, m, r;
    int head[N], cnt = 0;
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    struct Tree{
        int l, r, val, lz;
    }tree[N * 4];
    int val[N], tval[N];
    int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
    int res = 0, tot = 0;
    
    void add(int u, int v){
        edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    void pushdown(int index){
        if(tree[index].lz){
            int temp = tree[index].lz;
            tree[index].lz = 0;
            tree[index << 1].val = temp;
            tree[index << 1 | 1].val = temp;
            tree[index << 1].lz = temp;
            tree[index << 1 | 1].lz = temp;
        }
    }
    
    void pushup(int index){
        if(tree[index << 1].val || tree[index << 1 | 1].val) tree[index].val = 1;
        else tree[index].val = 0;
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l, tree[index].r = r;
        tree[index].lz = 0;
        if(l == r){
            tree[index].val = 0;
            // tpp[l] = index;
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata(int l, int r, int index, int val){
        if(tree[index].l >= l && tree[index].r <= r){
            tree[index].lz = val;
            tree[index].val = val;
            return;
        }
        pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata(l, r, index << 1, val);
        if(r > mid) updata(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    int query(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].val;
        }
        pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        ll ans = 0;
        if(l <= mid) ans += query(l, r, index << 1);
        if(r > mid) ans += query(l, r, index << 1 | 1);
        return ans > 0 ? 1 : 0;
    }
    
    // --------------------------------
    
    void Csol(int x, int y){
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            updata(dfn[top[x]], dfn[x], 1, 1);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        updata(dfn[x] + 1, dfn[y], 1, 1);    
    }
    
    void Usol(int x, int y){
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            updata(dfn[top[x]], dfn[x], 1, 0);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        updata(dfn[x] + 1, dfn[y], 1, 0);
    }
    
    int Qsol(int x, int y){
        int ans = 0;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            ans += query(dfn[top[x]], dfn[x], 1);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        ans += query(dfn[x] + 1, dfn[y], 1);
        return ans != 0;
    }
    
    
    
    
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        fa[u] = pre;
        siz[u] = 1;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == pre) continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){ //topu当前链的最顶端的节点
        dfn[u] = ++ tot;
        tval[tot] = val[u];
        top[u] = topu;
        rnk[tot] = u;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == son[u] || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    // void print(){
        // for(int i = 1; i <= n; ++ i){
            // int tt = tpp[dfn[i]];
            // cout<<tree[tt].val;
        // }
        // cout<<endl;
    // }
    
    int ax[N], ay[N], cnum = 0;
    
    int main()
    {
        scanf("%d%d",&n,&m);
        cnt = 0;
        for(int i = 0; i <= n; ++ i) head[i] = -1;
        for(int i = 1; i < n; ++ i){
            int x, y; scanf("%d%d",&x,&y);
            add(x, y);
        }
        dfs1(1, 0);
        dfs2(1, 1);
        Build(1, n, 1);
        
        char op[5];
        while(m --){
            scanf("%s",op);
            if(op[0] == 'C'){
                int x, y; scanf("%d%d",&x,&y);
                ax[++ cnum] = x, ay[cnum] = y;
                Csol(x, y);
            }
            else if(op[0] == 'U'){
                int x; scanf("%d",&x);
                Usol(ax[x], ay[x]);
            }
            else{
                int x, y; scanf("%d%d",&x,&y);
                if(Qsol(x, y)) printf("No
    ");
                else printf("Yes
    ");
            }
            
        }
        return 0;
    }
    

    P4114 Qtree1

    /*
    P4114
    树链剖分
    2020/8/19/9:41
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    // const ll mod = 1e9 + 7;
    int mod;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    
    int tpp[N];
    
    int n, m, r;
    int head[N], cnt = 0;
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    struct Tree{
        int l, r, val, lz;
    }tree[N * 4];
    int val[N], tval[N];
    int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
    int res = 0, tot = 0;
    
    void add(int u, int v, int w){
        edge[cnt].to = v, edge[cnt].c = w, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].c = w, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    void pushdown(int index){
        if(tree[index].lz){
            int temp = tree[index].lz;
            tree[index].lz = 0;
            tree[index << 1].val = temp;
            tree[index << 1 | 1].val = temp;
            tree[index << 1].val = temp;
            tree[index << 1 | 1].val = temp;
        }
    }
    
    void pushup(int index){
        tree[index].val = max(tree[index << 1].val, tree[index << 1 | 1].val);
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l, tree[index].r = r;
        tree[index].lz = 0;
        if(l == r){
            tree[index].val = tval[l];
            tpp[l] = index;
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata(int l, int r, int index, int val){
        if(tree[index].l >= l && tree[index].r <= r){
            tree[index].lz = val;
            tree[index].val = val;
            return;
        }
        pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata(l, r, index << 1, val);
        if(r > mid) updata(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    int query(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].val;
        }
        pushdown(index);
        int mid = (tree[index].l + tree[index].r) >> 1;
        int ans = 0;
        if(l <= mid) ans = max(ans, query(l, r, index << 1));
        if(r > mid) ans = max(ans, query(l, r, index << 1 | 1));
        return ans;
    }
    
    // --------------------------------
    
    void Csol(int x, int y, int val){
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            updata(dfn[top[x]], dfn[x], 1, val);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        updata(dfn[x] + 1, dfn[y], 1, val);    
    }
    
    int Qsol(int x, int y){
        int ans = 0;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            ans = max(ans, query(dfn[top[x]], dfn[x], 1));
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        ans = max(ans, query(dfn[x] + 1, dfn[y], 1));
        return ans;
    }
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        fa[u] = pre;
        siz[u] = 1;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to, w = edge[i].c;
            if(v == pre) continue;
            val[v] = w;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){ //topu当前链的最顶端的节点
        dfn[u] = ++ tot;
        tval[tot] = val[u];
        top[u] = topu;
        rnk[tot] = u;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == son[u] || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    // void print(){
        // for(int i = 1; i <= n; ++ i){
            // int tt = tpp[dfn[i]];
            // cout<<tree[tt].val<<" ";
        // }
        // cout<<endl;
    // }
    
    int ax[N], ay[N];
    
    int main()
    {
        scanf("%d",&n);
        cnt = 0;
        for(int i = 0; i <= n; ++ i) head[i] = -1;
        for(int i = 1; i < n; ++ i){
            int z; scanf("%d%d%d",&ax[i],&ay[i],&z);
            add(ax[i], ay[i], z);
        }
        dfs1(1, 0);
        dfs2(1, 1);
        Build(1, n, 1);
        
        char op[10];
        while(1){
            scanf("%s",op);
            if(op[0] == 'D') break;
            else if(op[0] == 'C'){
                int x, y; scanf("%d%d",&x,&y);
                Csol(ax[x], ay[x], y);
            }
            else{
                int x, y; scanf("%d%d",&x,&y);
                if(x == y) printf("0
    ");
                else printf("%d
    ",Qsol(x, y));
            }
        }
        return 0;
    }
    

    P4116 Qtree3

    /*
    P4116
    2020/8/19/9:47
    树链剖分
    */
    
    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    const int N = 2e6+ 5;
    const ll mod = 1e9 + 7;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
    bool cmp(int a, int b){ return a > b;}
    //
    
    
    int n, m, r;
    int head[N], cnt = 0;
    struct node{
        int to, nxt, c;
    }edge[N << 1];
    
    struct Tree{
        int l, r, val, lz;
    }tree[N * 4];
    int val[N], tval[N];
    int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
    int res = 0, tot = 0;
    
    void add(int u, int v){
        edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    
    void pushup(int index){
        tree[index].val = min(tree[index << 1].val , tree[index << 1 | 1].val);
    }
    
    void Build(int l, int r, int index){
        tree[index].l = l, tree[index].r = r;
        tree[index].lz = 0;
        if(l == r){
            tree[index].val = INF;
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, index << 1);
        Build(mid + 1, r, index << 1 | 1);
        pushup(index);
    }
    
    void updata(int l, int r, int index, int val){
        if(tree[index].l == tree[index].r){
            if(tree[index].val == INF) tree[index].val = val;
            else tree[index].val = INF;
            return;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        if(l <= mid) updata(l, r, index << 1, val);
        if(r > mid) updata(l, r, index << 1 | 1, val);
        pushup(index);
    }
    
    int query(int l, int r, int index){
        if(l <= tree[index].l && tree[index].r <= r){
            return tree[index].val;
        }
        int mid = (tree[index].l + tree[index].r) >> 1;
        int ans = INF;
        if(r > mid) ans = min(ans, query(l, r, index << 1 | 1));
        if(l <= mid) ans = min(ans, query(l, r, index << 1));
        return ans;
    }
    // --------------------------------
    
    int qRange(int x, int y){ //x 到 y树上最短路径结点权值和
        int res = INF;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            res = min(res, query(dfn[top[x]], dfn[x], 1));
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        res = min(res, query(dfn[x], dfn[y], 1));
        return res;
    }
    
    void dfs1(int u, int pre){
        dep[u] = dep[pre] + 1;
        fa[u] = pre;
        siz[u] = 1;
        int maxx = -1;
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == pre) continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[v] > maxx){
                maxx = siz[v];
                son[u] = v;
            }
        }
    }
    
    void dfs2(int u, int topu){ //topu当前链的最顶端的节点
        dfn[u] = ++ tot;
        top[u] = topu;
        rnk[tot] = u;
        if(!son[u]) return;
        dfs2(son[u], topu);
        for(int i = head[u]; i != -1; i = edge[i].nxt){
            int v = edge[i].to;
            if(v == son[u] || v == fa[u]) continue;
            dfs2(v, v);
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        cnt = 0;
        for(int i = 0; i <= n; ++ i) head[i] = -1;
        for(int i = 1; i < n; ++ i){
            int x, y; scanf("%d%d",&x,&y);
            add(x, y);
        }
        dfs1(1, 0);
        dfs2(1, 1);
        Build(1, n, 1);
        int op;
        while(m --){
            int x; scanf("%d%d",&op,&x);
            if(op == 0){
                updata(dfn[x], dfn[x], 1, dfn[x]);
            }
            else{
                int tt = qRange(1, x); 
                if(tt != INF) printf("%d
    ",rnk[tt]);
                else printf("-1
    ");
            }
        }
        return 0;
    }
    

    P3401 洛谷树

    
    

    P1505 国家集训队]旅游

    
    

    P3250 HNOI2016]网络

    
    
  • 相关阅读:
    Golang1.14.2 环境的安装
    Golang Module快速入门
    VS Code配置Go语言开发环境
    Go语言Mac、Linux、Windows 下交叉编译
    centerOS7 Yum 安装lnmp环境
    初步了解Fork/Join框架
    聊聊并发(七)——Java中的阻塞队列
    如何快速成长为技术大牛
    多线程-interrupt(),isInterrupted(),interrupted()(转)
    Rabbit MQ
  • 原文地址:https://www.cnblogs.com/A-sc/p/13528312.html
Copyright © 2020-2023  润新知