https://www.luogu.org/problem/show?pid=2590#sub

题目描述

一棵树上有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之间。

树剖模板

 #include <algorithm>
#include <string>
#include <cstdio> using namespace std; const int N(+);
int n,u,v,val[N],q;
char op[]; int head[N],sumedge;
struct Edge
{
int u,v,next;
Edge(int u=,int v=,int next=):
u(u),v(v),next(next){}
}edge[N<<];
void ins(int u,int v)
{
edge[++sumedge]=Edge(u,v,head[u]);
head[u]=sumedge;
} int cnt,id[N],dfn[N],size[N],son[N],top[N],dad[N],deep[N];
void DFS(int u,int father,int deepth)
{
deep[u]=deepth;
dad[u]=father;
size[u]=;
son[u]=;
for(int i=head[u];i;i=edge[i].next)
{
int to=edge[i].v;
if(dad[u]==to) continue;
DFS(to,u,deepth+); size[u]+=size[to];
if(!son[u]||size[son[u]]<size[to]) son[u]=to;
}
}
void DFS_(int u,int Top)
{
top[u]=Top;
id[u]=++cnt;
dfn[cnt]=u;
if(son[u]) DFS_(son[u],Top);
for(int i=head[u];i;i=edge[i].next)
{
int to=edge[i].v;
if(to!=dad[u]&&to!=son[u]) DFS_(to,to);
}
} struct Tree
{
int l,r,mid,sumval,maxval;
}tree[N<<];
void Tree_up(int now)
{
tree[now].sumval=tree[now<<].sumval+tree[now<<|].sumval;
tree[now].maxval=max(tree[now<<].maxval,tree[now<<|].maxval);
}
void Tree_build(int now,int l,int r)
{
tree[now].l=l;tree[now].r=r;
if(l==r)
{
tree[now].maxval=val[dfn[l]];
tree[now].sumval=val[dfn[l]];
return ;
}
tree[now].mid=l+r>>;
Tree_build(now<<,l,tree[now].mid);
Tree_build(now<<|,tree[now].mid+,r);
Tree_up(now);
}
void Tree_change(int now,int to,int x)
{
if(tree[now].l==tree[now].r)
{
tree[now].maxval=x;
tree[now].sumval=x;
return ;
}
if(tree[now].mid>=to) Tree_change(now<<,to,x);
else if(tree[now].mid<to) Tree_change(now<<|,to,x);
Tree_up(now);
}
int Tree_querymax(int now,int l,int r)
{
if(tree[now].l==l&&tree[now].r==r) return tree[now].maxval;
if(tree[now].mid>=r) return Tree_querymax(now<<,l,r);
else if(tree[now].mid<l) return Tree_querymax(now<<|,l,r);
else return max(Tree_querymax(now<<,l,tree[now].mid),Tree_querymax(now<<|,tree[now].mid+,r));
}
int Tree_querysum(int now,int l,int r)
{
if(tree[now].l==l&&tree[now].r==r) return tree[now].sumval;
if(tree[now].mid>=r) return Tree_querysum(now<<,l,r);
else if(tree[now].mid<l) return Tree_querysum(now<<|,l,r);
else return Tree_querysum(now<<,l,tree[now].mid)+Tree_querysum(now<<|,tree[now].mid+,r);
} int List_querymax(int x,int y)
{
int ret=-1e9;
for(;top[x]!=top[y];x=dad[top[x]])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
ret=max(ret,Tree_querymax(,id[top[x]],id[x]));
}
if(id[x]>id[y]) swap(x,y);
ret=max(ret,Tree_querymax(,id[x],id[y]));
return ret;
}
int List_querysum(int x,int y)
{
int ret=;
for(;top[x]!=top[y];x=dad[top[x]])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
ret+=Tree_querysum(,id[top[x]],id[x]);
}
if(id[x]>id[y]) swap(x,y);
ret+=Tree_querysum(,id[x],id[y]);
return ret;
} int main()
{
scanf("%d",&n);
for(int i=;i<n;i++)
scanf("%d%d",&u,&v),ins(u,v),ins(v,u);
for(int i=;i<=n;i++) scanf("%d",val+i);
DFS(,,);DFS_(,);
Tree_build(,,n);
scanf("%d",&q);
for(;q--;)
{
scanf("%s%d%d",op,&u,&v);
if(op[]=='C') Tree_change(,id[u],v);
else if(op[]=='M') printf("%d\n",List_querymax(u,v));
else printf("%d\n",List_querysum(u,v));
}
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] 树的统计 [树链剖分]

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

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

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

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

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

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

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

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

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

  7. 洛谷.2590.[ZJOI2008]树的统计(树分块)

    题目链接 Update:这种分块写法...可以被卡掉啊... 好像没有靠谱的树分块写法... /* 对树上节点进行分块,每个点记录dep,fa,val,Max,Sum,Max,Sum表示当前点在该块内 ...

  8. P2590 [ZJOI2008]树的统计(树链剖分)

    P2590 [ZJOI2008]树的统计 虽然是入门树剖模板 但是我终于1A了(大哭) 懒得写啥了(逃 #include<iostream> #include<cstdio> ...

  9. P2590 [ZJOI2008]树的统计(LCT)

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

随机推荐

  1. BZOJ 3787 Gty的文艺妹子序列(分块+树状数组+前缀和)

    题意 给出n个数,要求支持单点修改和区间逆序对,强制在线. n,m<=50000 题解 和不带修改差不多,预处理出smaller[i][j]代表前i块小于j的数的数量,但不能用f[i][j]代表 ...

  2. CF949C Data Center Maintenance(建图+强联通分量)

    题意 有 n 个信息中心,第 i 个信息中心要在第 ti 个小时维护,维护期间信息不能被获得. 每个用户的数据都有两份备份,第 i 个用户的数据放在信息中心 c(i,1) 和 c(i,2). 现在要挑 ...

  3. HNU 11979 Roll call 二分图匹配

    题意: 众所周知,老师经常在班级上点名.点名是从名单上叫一个人的名字或者id来判断名单上这个人是否在场.学生们总是有各种各样的理由不来,所以他们需要其他人帮他们答到.但是打到工作不是这么简单,出于各种 ...

  4. Android编译环境配置

    Android编译环境配置 网上关于Android编译环境配置的整理资料有不少,经整理亲测后,希望能给需要的亲们提供帮助. 主要分为四步: 1.安装JDK(Java Standard Edition ...

  5. 关于App程序猿泡沫

    前言 做开发快七年了,对于程序猿,外行人总有着数不完的讽刺和误解,可是我都懒得去解释.代码搬运工人也好,民工也罢,随他们去说吧.可是网上近期流传的程序猿泡沫,尤其是APP程序猿泡沫的文章导致非常多我们 ...

  6. matlab 常用机器学习算法的实现

    1. KNN 分类 load fisheriris X = meas; Y = species; % 3 分类问题 % 通过训练集进行训练 Mdl = fitcknn(X, Y, 'NumNeighb ...

  7. 123.static静态函数与类模板

    #include <iostream> using namespace std; //静态函数没有this指针,无需创建对象就可以直接调用 template<class T> ...

  8. 35.QQ大数据模型

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <stri ...

  9. .net数字转换成汉字大写

    public class Num2Rmb { private String[] hanArr={"零","壹","贰","叁&qu ...

  10. JAVA工程命名规范

    Java推荐的包声明命名约定是反向域名. 例如 - com.abysm.myproject