思路:

树链剖分,不知道说什么...我连模板都不会用

代码:

#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
const int maxn = 60000+5;
const int INF = 0x3f3f3f3f;
using namespace std;
int n,m,tol;
int cnt;
struct Node{
    int u,v,next;
}node[maxn << 1];
int head[maxn];
int fa[maxn],siz[maxn],dep[maxn],son[maxn],id[maxn],top[maxn];
//父节点,子树大小,深度,重儿子,dfs执行顺序,重链的起始点

void addnode(int u,int v){
    node[tol].u = u;
    node[tol].v = v;
    node[tol].next = head[u];
    head[u] = tol++;
}
void dfs1(int u,int father,int depth){  //确定fa,siz,dep,son
    son[u] = 0;
    dep[u] = depth;
    fa[u] = father;
    siz[u] = 1;
    for(int i = head[u];~i;i = node[i].next){
        int v = node[i].v;
        if(v == father) continue;   //储存无向边,需判断
        dfs1(v,u,depth + 1);
        siz[u] += siz[v];
        if(siz[v] > siz[son[u]])    //更新重儿子
            son[u] = v;
    }
}
void dfs2(int u,int tp){    //按dfs执行顺序编号
    top[u] = tp;    //重链的起始点
    id[u] = ++cnt;  //编号
    if(!son[u]) return;
    //有重儿子,是重链,继续往下
    dfs2(son[u],tp);
    for(int i = head[u];~i;i = node[i].next){
        int v = node[i].v;
        if(v == fa[u] || v == son[u]) continue;
        dfs2(v,v);
    }
}

/*
线段树
*/
int sum[maxn<<2],mx[maxn<<2];

void push_up(int rt){
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    mx[rt] = max(mx[rt << 1],mx[rt << 1 | 1]);
}
/*void build(int l,int r,int rt){
    sum[rt] = 0;
    mx[rt] = -INF;  //注意
    if(l == r){
        sum[rt] = mx[rt] = val[l];
        return;
    }
    int m = (l + r) >> 1;
    build(l,m,rt << 1);
    build(m + 1,r,rt << 1 | 1);
    push_up(rt);
}*/
void update(int pos,int val,int l,int r,int rt){
    if(l == r){
        sum[rt] = mx[rt] = val;
        return;
    }
    int m = (l + r) >> 1;
    if(pos <= m)
        update(pos,val,l,m,rt << 1);
    else
        update(pos,val,m + 1,r,rt << 1 | 1);
    push_up(rt);
}
int queryS(int L,int R,int l,int r,int rt){
    if(L <= l && R >= r){
        return sum[rt];
    }
    int m = (l + r) >> 1;
    int ans = 0;
    if(L <= m)
        ans += queryS(L,R,l,m,rt << 1);
    if(R > m)
        ans += queryS(L,R,m + 1,r,rt << 1 | 1);
    return ans;
}
int queryM(int L,int R,int l,int r,int rt){
    if(L <= l && R >= r){
        return mx[rt];
    }
    int m = (l + r) >> 1;
    int ans = -INF;
    if(L <= m)
        ans = max(ans,queryM(L,R,l,m,rt << 1));
    if(R > m)
        ans = max(ans,queryM(L,R,m + 1,r,rt << 1 | 1));
    return ans;
}

//////////////////////////////////////////
int FindS(int u,int v){
    int ans = 0;
    while(top[u] != top[v]){    //不在同一条链上,就从u所在转移到v所在
        if(dep[top[u]] < dep[top[v]]){
            swap(u,v);
        }
        ans += queryS(id[top[u]],id[u],1,n,1);
        u = fa[top[u]];
    }
    if(u == v){
        return (ans + queryS(id[u],id[v],1,n,1));
    }
    else{
        if(dep[u] > dep[v]){
            swap(u,v);
        }
        return (ans + queryS(id[u],id[v],1,n,1));
    }
}
int FindM(int u,int v){
    int ans = -INF;
    while(top[u] != top[v]){    //不在同一条链上,就从u所在转移到v所在
        if(dep[top[u]] < dep[top[v]]){
            swap(u,v);
        }
        ans = max(ans,queryM(id[top[u]],id[u],1,n,1));
        u = fa[top[u]];
    }
    if(u == v){
        return max(ans,queryM(id[u],id[v],1,n,1));
    }
    else{
        if(dep[u] > dep[v]){
            swap(u,v);
        }
        return max(ans,queryM(id[u],id[v],1,n,1));
    }
}
///////////////////////////////////////////////////

void init() {
    tol = cnt = 0;
    memset(fa,0,sizeof fa);
    memset(siz,0,sizeof siz);
    memset(son,0,sizeof son);
    memset(dep,0,sizeof dep);
    memset(top,0,sizeof top);
    memset(id,0,sizeof id);
    memset(sum,0,sizeof sum);
    memset(node,0,sizeof node);
    memset(mx,0,sizeof mx);
    memset(head,-1,sizeof head);
}
int main(){
    int q;
    while(~scanf("%d",&n)){
        int u,v;
        init();
        for(int i = 1;i < n;i++){
            scanf("%d%d",&u,&v);
            addnode(u,v);
            addnode(v,u);
        }
        dfs1(1,0,1);
        dfs2(1,1);
        for(int i = 1;i <= n;i++){
            int w;
            scanf("%d",&w);
            update(id[i],w,1,n,1);
        }
        scanf("%d",&q);
        char s[20];
        while(q--){
            scanf("%s%d%d",s,&u,&v);
            if(s[0] == 'C'){
                update(id[u],v,1,n,1);
            }
            else if(s[1] == 'S'){
                printf("%d\n",FindS(u,v));
            }
            else{
                printf("%d\n",FindM(u,v));
            }
        }
    }
    return 0;
}
J

HYSBZ 1036 树的统计Count(树链剖分)题解的更多相关文章

  1. BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14302  Solved: 5779[Submit ...

  2. Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 11102  Solved: 4490[Submit ...

  3. BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )

    树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...

  4. bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 16294  Solved: 6645[Submit ...

  5. BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14982  Solved: 6081[Submit ...

  6. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分)(线段树单点修改)

    [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14968  Solved: 6079[Submit][Stat ...

  7. 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分

    [BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...

  8. bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题

    [ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...

  9. Cogs 1688. [ZJOI2008]树的统计Count(树链剖分+线段树||LCT)

    [ZJOI2008]树的统计Count ★★★ 输入文件:bzoj_1036.in 输出文件:bzoj_1036.out 简单对比 时间限制:5 s 内存限制:162 MB [题目描述] 一棵树上有n ...

  10. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...

随机推荐

  1. luogu P2066 机器分配[背包dp+方案输出]

    题目背景 无 题目描述 总公司拥有高效设备M台,准备分给下属的N个分公司.各分公司若获得这些设备,可以为国家提供一定的盈利.问:如何分配这M台设备才能使国家得到的盈利最大?求出最大盈利值.其中M≤15 ...

  2. IIS7的HTTP到HTTPS的重定向

    方法一设置IIS 从HTTP到HTTPS的IIS7中的所有流量重定向,将确保用户始终安全地访问该网站.有许多不同的方法来设置一个IIS7从HTTP重定向到HTTPS和一些比别人更好.理想的HTTP到H ...

  3. VMware Fusion 5虚拟机怎样与MAC共享文件

    刚刚在Macbook Pro中安装了VMware Fusion 5虚拟机,虚拟机里装了Windows7,在虚拟机的设置里也设置了共享MAC的几个文件夹,以便与MAC交换文件,但是在Windows7里怎 ...

  4. Javascript一(变量,数据类型,正则表达式,数据,语句)

    本文章适合具有一定程序编程语言基础的人士阅读,最好学完Java基础再来阅读本文章更容易理解语言初学者会看起来比较费劲,不易理解 一.导入脚本 在html导入Javascript的格式是: <sc ...

  5. jps命令用法

    jps是jdk提供的一个查看当前java进程的小工具, 可以看做是JavaVirtual Machine Process Status Tool的缩写.非常简单实用. 命令格式:jps [option ...

  6. Why do some system users have /usr/bin/false as their shell? What's the difference between /sbin/nologin and /bin/false

    https://www.quora.com/How-can-bin-true-and-bin-false-Linux-utilities-be-used MySQL :: MySQL 8.0 Refe ...

  7. collision weaknesses

    15.1. hashlib — Secure hashes and message digests — Python 3.5.6 documentation https://docs.python.o ...

  8. 获取List、Set、Map等字段的泛型参数

    测试类加单元测试方法,运行结果在注释里面: package temp; import org.junit.Test; import java.lang.reflect.Field; import ja ...

  9. jQuery.outerWidth() 函数具体解释

    outerWidth()函数用于设置或返回当前匹配元素的外宽度.外宽度默认包含元素的内边距(padding).边框(border),但不包含外边距(margin)部分的宽度.你也能够指定參数为true ...

  10. web项目读取classpath路径下面的文件

    首先分两大类按web容器分类 一种是普通的web项目,像用Tomcat容器,特点是压缩包随着容器的启动会解压缩成一个文件夹,项目访问的时候,实际是去访问文件夹,而不是jar或者war包. 这种的无论你 ...