zoukankan      html  css  js  c++  java
  • P4315 月下“毛景树”

    (color{#0066ff}{题目描述})

    毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。

    爬啊爬~爬啊爬毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:

    Change k w:将第k条树枝上毛毛果的个数改变为w个。
    
    Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。
    
    Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:
    
    Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
    

    (color{#0066ff}{输入格式})

    第一行一个正整数N。

    接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。

    (color{#0066ff}{输出格式})

    对于毛毛虫的每个询问操作,输出一个答案。

    (color{#0066ff}{输入样例})

    4
    1 2 8
    1 3 7
    3 4 9
    Max 2 4
    Cover 2 4 5
    Add 1 4 10
    Change 1 16
    Max 2 4
    Stop
    

    (color{#0066ff}{输出样例})

    9
    16
    

    (color{#0066ff}{数据范围与提示})

    1<=N<=100,000,操作+询问数目不超过100,000。

    保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。

    (color{#0066ff}{题解})

    树剖维护,把边权转成点权

    线段树维护一个变成,一个加

    变成的时候把add清空

    求链的时候,会发现LCA是没用的,所以最后+1,把lca去掉

    #include <bits/stdc++.h>
    
    #define LL long long
    
    const int maxn = 1e5 + 10;
    
    LL in() {
        char ch; int x = 0, f = 1;
        while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
        while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
        return x * f;
    }
    
    struct node {
        int to, dis, id;
        node *nxt;
        node(int to = 0, int dis = 0, int id = 0, node *nxt = NULL):to(to), dis(dis), id(id), nxt(nxt) {}
        void *operator new (size_t) {
            static node *S = NULL, *T = NULL;
            return (S == T) && (T = (S = new node[1024]) + 1024), S++;
        }
    };
    node *head[maxn];
    
    struct sgt {
        int l, r, add, bc, max;
        sgt *ch[2];
        sgt(int l = 0, int r = 0, int add = 0, int bc = -1, int max = 0):l(l), r(r), add(add), bc(bc), max(max) {}
        void *operator new (size_t) {
            static sgt *S = NULL, *T = NULL;
            return (S == T) && (T = (S = new sgt[1024]) + 1024), S++;
        }
        void upd() {max = std::max(ch[0]->max, ch[1]->max);}
        void dwn() {
            if(~bc) {
                ch[0]->max = ch[1]->max = bc;
                ch[0]->bc = ch[1]->bc = bc;
                ch[0]->add = ch[1]->add = 0;
                bc = -1;
            }
            if(add) {
                ch[0]->max += add;
                ch[1]->max += add;
                ch[0]->add += add;
                ch[1]->add += add;
                add = 0;
            }
        }
    };
    sgt *root;
    
    int dep[maxn], fa[maxn], siz[maxn], dfn[maxn], redfn[maxn], son[maxn], top[maxn], val[maxn], e[maxn];
    int n, cnt;
    
    void add(int from, int to, int dis, int id) {
        node *o = new node(to, dis, id, head[from]);
        head[from] = o;
    }
    
    char getch() {
        char ch;
        while(!isalpha(ch = getchar()));
        return ch;
    }
    
    void dfs1(int x, int f) {
        dep[x] = dep[f] + 1;
        siz[x] = 1;
        fa[x] = f;
        for(node *i = head[x]; i; i = i->nxt) {
            if(i->to == f) continue;
            val[i->to] = i->dis;
            e[i->id] = i->to;
            dfs1(i->to, x);
            siz[x] += siz[i->to];
            if(!son[x] || siz[i->to] > siz[son[x]]) son[x] = i->to;
        }
    }
    
    void dfs2(int x, int t) {
        dfn[x] = ++cnt;
        redfn[cnt] = x;
        top[x] = t;
        if(son[x]) dfs2(son[x], t);
        for(node *i = head[x]; i; i = i->nxt)
            if(!dfn[i->to]) dfs2(i->to, i->to);
    }
    
    void build(sgt *&o, int l, int r) {
        o = new sgt(l, r, 0, -1, 0);
        if(l == r) return (void)(o->max = val[redfn[l]]);
        int mid = (l + r) >> 1;
        build(o->ch[0], l ,mid);
        build(o->ch[1], mid + 1, r);
        o->upd();
    }
    
    void change(sgt *o, int l, int r, int k) {
        if(o->l > r || o->r < l) return;
        if(l <= o->l && o->r <= r) {
            o->max = k;
            o->add = 0;
            o->bc = k;
            return;
        }
        o->dwn();
        change(o->ch[0], l, r, k), change(o->ch[1], l, r, k);
        o->upd();
    }
    
    void lazy(sgt *o, int l, int r, int k) {
        if(o->l > r || o->r < l) return;
        if(l <= o->l && o->r <= r) {
            o->max += k;
            o->add += k;
            return;
        }
        o->dwn();
        lazy(o->ch[0], l, r, k), lazy(o->ch[1], l, r, k);
        o->upd();
    }
    
    int query(sgt *o, int l, int r) {
        if(o->l > r || o->r < l) return -1;
        if(l <= o->l && o->r <= r) return o->max;
        o->dwn();
        return std::max(query(o->ch[0], l, r), query(o->ch[1], l, r));
    }
    
    void changepath(int x, int y, int z) {
        int fx = top[x], fy = top[y];
        while(fx != fy) {
            if(dep[fx] >= dep[fy]) {
                change(root, dfn[fx], dfn[x], z);
                x = fa[fx];
            }
            else {
                change(root, dfn[fy], dfn[y], z);
                y = fa[fy];
            }
            fx = top[x], fy = top[y];
        }
        if(dep[y] < dep[x]) std::swap(x, y);
        change(root, dfn[x] + 1 ,dfn[y], z);
    }
    
    void addpath(int x, int y, int z) {
        int fx = top[x], fy = top[y];
        while(fx != fy) {
            if(dep[fx] >= dep[fy]) {
                lazy(root, dfn[fx], dfn[x], z);
                x = fa[fx];
            }
            else {
                lazy(root, dfn[fy], dfn[y], z);
                y = fa[fy];
            }
            fx = top[x], fy = top[y];
        }
        if(dep[y] < dep[x]) std::swap(x, y);
        lazy(root, dfn[x] + 1 ,dfn[y], z);
    }
    
    int querymax(int x, int y) {
        int ans = 0;
        int fx = top[x], fy = top[y];
        while(fx != fy) {
            if(dep[fx] >= dep[fy]) {
                ans = std::max(ans, query(root, dfn[fx], dfn[x]));
                x = fa[fx];
            }
            else {
                ans = std::max(ans, query(root, dfn[fy], dfn[y]));
                y = fa[fy];
            }
            fx = top[x], fy = top[y];
        }
        if(dep[y] < dep[x]) std::swap(x, y);
        return std::max(ans, query(root, dfn[x] + 1, dfn[y]));
    }
    
    int main() {
        n = in();
        int x, y, z;
        for(int i = 1; i < n; i++) {
            x = in(), y = in(), z = in();
            add(x, y, z, i);
            add(y, x ,z ,i);
        }
        dfs1(1, 0);
        dfs2(1, 1);
        build(root, 1, n);
        while("xu mao zhe shi dalao %%%%%%% ") {
            char ch = getch();
            if(ch == 'S') break;
            if(ch == 'C') {
                if(getch() == 'h') x = in(), y = in(), change(root, dfn[e[x]], dfn[e[x]], y);
                else x = in(), y = in(), z = in(), changepath(x, y, z); 
            }
            if(ch == 'A') x = in(), y = in(), z = in(), addpath(x, y, z); 
            if(ch == 'M') x = in(), y = in(), printf("%d
    ", querymax(x, y));
        }
        return 0;
    }
    
    
  • 相关阅读:
    关于数组的一些面试题目及答案
    java类的定义以及参数传递
    第39届大学生程序设计大赛亚洲区域赛广州站比赛总结
    模拟退火法(吊打XXX)Bzoj3680
    树链剖分(单点更新,求区间最值,区间求和Bzoj1036)
    树链剖分(线段树区间更新求和(lazy操作)hdu3966)
    最大权闭合图(Road constructions)hdu3917
    最大权闭合图最大获益(把边抽象为点)HDU3879
    最大权闭合图hdu3996
    最大密集子图(01分数规划+二分+最小割)POJ3155
  • 原文地址:https://www.cnblogs.com/olinr/p/10152254.html
Copyright © 2011-2022 走看看