题目传送门

树的统计

题目描述

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。

我们将以下面的形式来要求你对这棵树完成一些操作:

I. CHANGE u t : 把结点u的权值改为t

II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

III. QSUM u v: 询问从点u到点v的路径上的节点的权值和

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

输入输出格式

输入格式:

输入文件的第一行为一个整数n,表示节点的个数。

接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。

接下来一行n个整数,第i个整数wi表示节点i的权值。

接下来1行,为一个整数q,表示操作的总数。

接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

输出格式:

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

输入输出样例

输入样例#1: 复制

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
输出样例#1: 复制

4
1
2
2
10
6
5
6
5
16

说明

对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。


  分析:

  一开始看到以为是个什么很难的数据结构,然后仔细看了一边题面,这不就是个树剖裸题吗?

  用结构体写会方便很多,而且因为只有单点修改,所以连下放标记都不需要。我一开始写了个SB特判卡了半天。。。。。。

  Code:

#include<bits/stdc++.h>
using namespace std;
const int inf=0x7f7f7f7f;
const int N=3e4+;
int n,m,a[N],head[N],cnt,id,dfn[N],nu[N];
int hson[N],fa[N],dep[N],top[N],size[N];
struct Node{int to,next;}edge[N<<];
struct Seg{
int tot;int mx;
friend Seg operator + (const Seg a,const Seg b)
{
Seg ret;
ret.tot=a.tot+b.tot;
ret.mx=max(a.mx,b.mx);
return ret;
}
}t[N<<];
inline int read()
{
char ch=getchar();int num=;bool flag=false;
while(ch<''||ch>''){if(ch=='-')flag=true;ch=getchar();}
while(ch>=''&&ch<=''){num=num*+ch-'';ch=getchar();}
return flag?-num:num;
}
inline void add(int x,int y)
{
edge[++cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt;
}
inline void dfs1(int u)
{
size[u]=;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(v==fa[u])continue;
fa[v]=u;dep[v]=dep[u]+;
dfs1(v);size[u]+=size[v];
if(size[v]>size[hson[u]])
hson[u]=v;}
}
inline void dfs2(int u,int now)
{
dfn[++id]=u;nu[u]=id;top[u]=now;
if(!hson[u])return;dfs2(hson[u],now);
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(v==fa[u]||v==hson[u])continue;
dfs2(v,v);}
}
inline void pushup(int rt)
{
t[rt]=t[rt<<]+t[rt<<|];
}
inline void build(int l,int r,int rt)
{
if(l>r)return;
if(l==r){
t[rt].tot=t[rt].mx=a[dfn[l]];
return;}
int mid=(l+r)>>;
build(l,mid,rt<<);
build(mid+,r,rt<<|);
pushup(rt);
}
inline void update(int l,int r,int rt,int L,int R,int C)
{
if(l>R||r<L)return;
if(l==L&&r==R){
t[rt].tot=t[rt].mx=C;
return;}
int mid=(l+r)>>;
update(l,mid,rt<<,L,R,C);
update(mid+,r,rt<<|,L,R,C);
pushup(rt);
}
inline Seg quary(int l,int r,int rt,int L,int R)
{
Seg ret;ret.tot=;ret.mx=-inf;
if(l>R||r<L)return ret;
if(L<=l&&r<=R)return t[rt];
int mid=(l+r)>>;
if(L<=mid)ret=ret+quary(l,mid,rt<<,L,R);
if(R>mid)ret=ret+quary(mid+,r,rt<<|,L,R);
return ret;
}
inline Seg get(int x,int y)
{
int fax=top[x],fay=top[y];
Seg ans;ans.tot=;ans.mx=-inf;
while(fax!=fay){
if(dep[fax]<dep[fay])swap(x,y),swap(fax,fay);
ans=ans+quary(,n,,nu[fax],nu[x]);
x=fa[fax];fax=top[x];}
if(x!=y){
if(dep[x]>dep[y])swap(x,y);}
ans=ans+quary(,n,,nu[x],nu[y]);
return ans;
}
int main()
{
n=read();int x,y;
memset(head,-,sizeof(head));
for(int i=;i<n;i++){
x=read();y=read();
add(x,y);add(y,x);}
for(int i=;i<=n;i++)
a[i]=read();
fa[]=;dep[]=;
dfs1();dfs2(,);
build(,n,);m=read();
for(int i=;i<=m;i++){
char opt[];
scanf("%s",opt);
x=read();y=read();
if(opt[]=='C')
update(,n,,nu[x],nu[x],y);
else {Seg ans=get(x,y);
if(opt[]=='M')printf("%d\n",ans.mx);
else printf("%d\n",ans.tot);}}
return ;
}

洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]的更多相关文章

  1. 洛谷——P2590 [ZJOI2008]树的统计(树链剖分模板练手)

    P2590 [ZJOI2008]树的统计 I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问 ...

  2. 洛谷P2590 [ZJOI2008]树的统计 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2590 树链剖分模板题. 剖分过程要用到如下7个值: fa[u]:u的父节点编号: dep[u]:u的深度: size[u]: ...

  3. [洛谷P2590][ZJOI2008]树的统计

    题目大意:一棵树,支持三个操作, $CHANGE\;u\;t:$ 把结点$u$的权值改为$t$ $QMAX\;u\;v:$ 询问从点$u$到点$v$的路径上的节点的最大权值 $QSUM\;u\;v:$ ...

  4. BZOJ 1036: [ZJOI2008]树的统计Count-树链剖分(点权)(单点更新、路径节点最值、路径求和)模板,超级认真写了注释啊啊啊

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

  5. 洛谷 P4292 - [WC2010]重建计划(长链剖分+线段树)

    题面传送门 我!竟!然!独!立!A!C!了!这!道!题!incredible! 首先看到这类最大化某个分式的题目,可以套路地想到分数规划,考虑二分答案 \(mid\) 并检验是否存在合法的 \(S\) ...

  6. 树的统计Count---树链剖分

    NEFU专项训练十和十一——树链剖分 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t ...

  7. 洛谷 P2590 [ZJOI2008]树的统计(树链剖分)

    题目描述一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...

  8. 洛谷 P2590 [ZJOI2008]树的统计

    大家好,我非常喜欢暴力数据结构,于是我用块状树过了这道题目 题目: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE ...

  9. 洛谷——P2590 [ZJOI2008]树的统计

    https://www.luogu.org/problem/show?pid=2590#sub 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这 ...

随机推荐

  1. poj 3376 Finding Palindromes

    Finding Palindromes http://poj.org/problem?id=3376 Time Limit: 10000MS   Memory Limit: 262144K       ...

  2. PHP日期时间操作

    一.设置时区 date_default_timezone_set('PRC'); 二.获取当前时间的 Unix 时间戳(格林威治时间 1970 年 1 月 1 日 00:00:00到当前时间的秒数)和 ...

  3. 「6月雅礼集训 2017 Day4」qyh(bzoj2687 交与并)

    原题传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2687 [题目大意] 给出若干区间,求一个区间的大于等于2的子集,使得 |区间并| 和 | ...

  4. Git彻底删除历史提交记录的方法

    有时候我们可能会遇到git提交错误的情况,比如提交了敏感的信息或者提交了错误的版本.这个时候我们想将提交到代码库的记录删除,我们要怎么做呢? 首先,我们需要找到我们需要回滚到的提交点的hash,可以使 ...

  5. 解决java在对MySQL插入数据时出现乱码问题

    1.在连接数据库的时候请注意, 最使用连接连接数据库的时候,必须在后面追加上编码的设置:useUnicode=true&characterEncoding=UTF-8,如下图所示. 参考连接: ...

  6. js常用模板引擎

    baiduTemplate(百度).artTemplate(腾讯).juicer(淘宝).xtemplate.doT.Jade 1.Handlebars 是 JavaScript 一个语义模板库,通过 ...

  7. mysql cast函数

    CAST函数语法规则是:Cast(字段名 as 转换的类型 ),其中类型可以为: CHAR[(N)] 字符型 DATE 日期型DATETIME 日期和时间型DECIMAL float型SIGNED i ...

  8. (八)hope

    vi svnserve.conf vi passwdvi authz svnserve -d -r /usr/svnkillall svnserveps -ef | grep svnserve svn ...

  9. C基础 万能动态数组

    引言 - 动态数组切入 开发中动态类型无外乎list 或者 vector, 这里就是在C中实现vector结构容器部分. 对于C中使用的数据结构, 可以参照下面感觉很不错框架源码学习 , 感觉是< ...

  10. 方便大家学习的Node.js教程(一):理解Node.js

    理解Node.js 为了理解Node.js是如何工作的,首先你需要理解一些使得Javascript适用于服务器端开发的关键特性.Javascript是一门简单而又灵活的语言,这种灵活性让它能够经受住时 ...