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

    题目描述

    原题来自:ZJOI 2008

    一树上有 个节点,编号分别为 到 ,每个节点都有一个权值 。我们将以下面的形式来要求你对这棵树完成一些操作:

    1. CHANGE u t :把节点 权值改为 ;
    2. QMAX u v :询问点 到点 路径上的节点的最大权值;
    3. QSUM u v :询问点 到点 路径上的节点的权值和。

    注意:从点 到点 路径上的节点包括 和 本身。

    输入格式

    第一行为一个数 ,表示节点个数;

    接下来 行,每行两个整数 ,表示节点 与节点 之间有一条边相连;

    接下来 行,每行一个整数,第 行的整数 表示节点 的权值;

    接下来一行,为一个整数 ,表示操作总数;

    接下来 行,每行一个操作,以 CHANGE u tQMAX u vQSUM u v的形式给出。

    输出格式

    对于每个 QMAXQSUM 的操作,每行输出一个整数表示要求的结果。

    样例

    样例输入

    4
    1 2
    2 3
    4 1
    4 2 1 3
    12
    QMAX 3 4
    QMAX 3 3
    QMAX 3 2
    QMAX 2 3
    QSUM 3 4
    QSUM 2 1
    CHANGE 1 5
    QMAX 3 4
    CHANGE 3 6
    QMAX 3 4
    QMAX 2 4
    QSUM 3 4
    

    样例输出

    4
    1
    2
    2
    10
    6
    5
    6
    5
    16
    
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 1e5+1000;
    int f[maxn], head[maxn], mod, rt, len, dfn[maxn], n, m, son[maxn], size[maxn], a[maxn], top[maxn], dep[maxn], cnt, rk[maxn];
    struct edge{ int to, next; } e[2*maxn];
    struct node{int l, r, w, siz, maxx; } tr[maxn<<2];
    void add(int x, int y){ e[++len].to=y; e[len].next=head[x]; head[x]=len; }
    void dfs1(int u, int fa){
        size[u] = 1;
        for(int i=head[u]; ~i; i=e[i].next){
            int v = e[i].to;
            if(v==fa) continue;
            dep[v] = dep[u] + 1;
            f[v] = u;
            dfs1(v, u);
            size[u] += size[v];
            if(!son[u] || size[v]>size[son[u]]) son[u] = v;
        }
    }
    void dfs2 (int u, int tp){
        top[u] = tp;
        dfn[u] = ++cnt;
        rk[cnt] = a[u];
        if(son[u]) dfs2(son[u], tp);
        for(int i=head[u]; ~i; i=e[i].next){
            int v = e[i].to;
            if(v!=son[u] && v!=f[u]) dfs2(v, v);
        }
    }
    void pushup(int u){ tr[u].w = tr[u<<1].w + tr[u<<1|1].w; }
    void change(int u, int x, int w){
        if(tr[u].l == tr[u].r){ tr[u].w = tr[u].maxx = w; return; }
        int mid = (tr[u].l + tr[u].r)>>1;
        if(x<=mid) change(u<<1, x, w);
        else change(u<<1|1, x, w);
        tr[u].maxx = max(tr[u<<1].maxx, tr[u<<1|1].maxx);
        pushup(u);
    }
    void build(int u, int l, int r){
        tr[u].l = l, tr[u].r = r, tr[u].siz = r - l + 1;
        if(l==r){ tr[u].w = tr[u].maxx = rk[l]; return; }
        int mid = (l+r)>>1;
        build(u<<1, l, mid); build(u<<1|1, mid+1, r);
        tr[u].maxx = max(tr[u<<1].maxx, tr[u<<1|1].maxx);
        pushup(u);
    }
    int query(int u, int l, int r){
        int ans = 0;
        if(l<=tr[u].l && r>=tr[u].r) return tr[u].w;
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(l<=mid) ans = ans + query(u<<1, l, r);
        if(r>mid)  ans = ans + query(u<<1|1, l, r);
        return ans;
    }
    int querysum(int u, int v){
        int ans = 0;
        while(top[u] != top[v]){
            if(dep[top[u]] < dep[top[v]]) swap(u, v);
            ans += query(1, dfn[top[u]], dfn[u]);
            u = f[top[u]];
        }
        if(dep[u] > dep[v]) swap(u, v);
        ans += query(1, dfn[u], dfn[v]);
        return ans;
    }
    int getmax(int u, int l, int r){
        if(l<=tr[u].l && r>=tr[u].r) return tr[u].maxx;
        int ans = -99999999;
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(l<=mid) ans = max(ans, getmax(u<<1, l, r));
        if(r>mid)  ans = max(ans, getmax(u<<1|1, l, r));
        return ans;
    }
    int treemax(int x, int y){
        int res = -999999;
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            res = max(res, getmax(1, dfn[top[x]], dfn[x]));
            x = f[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        res = max(res, getmax(1, dfn[x], dfn[y]));
        return res;
    }
    int main(){
        memset(head, -1, sizeof(head));
        scanf("%d", &n);
        for(int i=1; i<n; i++){
            int x, y; scanf("%d%d", &x, &y);
            add(x, y); add(y, x);
        }
        for(int i=1; i<=n; i++) scanf("%d", &a[i]);
        int q; scanf("%d", &q);
        dfs1(1, 0);
        dfs2(1, 1);
        build(1, 1, n);
        while(q--){
            int u, v;
            char ch[10]; scanf("%s%d%d", ch, &u, &v);
            if(ch[1] == 'M') printf("%d
    ", treemax(u, v));
            else if(ch[1] == 'S') printf("%d
    ", querysum(u, v));
            else if(ch[1] == 'H') change(1, dfn[u], v);
        }
        return 0;
    }
    
  • 相关阅读:
    《Java TCP/IP Socket 编程 》读书笔记之十一:深入剖析socket——TCP套接字的生命周期
    c++实现二分查找
    hadoop序列化机制与java序列化机制对比
    C、C++中“*”操作符和“后++”操作符的优先级
    poj2774之最长公共子串
    Python之美[从菜鸟到高手]--urlparse源码分析
    (程序员面试题)字符串处理之寻找最大不重复子串
    hdu 4782 Beautiful Soupz
    教程Xcode 下编译发布与提交App到AppStore
    云端的ABAP Restful服务开发
  • 原文地址:https://www.cnblogs.com/hzoi-poozhai/p/12886637.html
Copyright © 2011-2022 走看看