【luogu P2590 [ZJOI2008]树的统计】 题解
题目链接:https://www.luogu.org/problemnew/show/P2590
我想学树剖QAQ
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 31000;
int fa[maxn], dep[maxn], size[maxn], son[maxn], top[maxn], seg[maxn], rev[maxn<<2];
int sum[maxn<<2], num[maxn], mx[maxn];
struct edge{
int to, next;
}e[maxn<<2];
int head[maxn<<2], cnt;
int summ, maxx, n, m;
void query(int k, int l, int r, int L, int R)//区间查询
{
if(L > r||R < l) return;
if(L <= l&&r <= R)
{
summ += sum[k];
maxx = max(maxx, mx[k]);
return;
}
int mid = l+r>>1, res = 0;
if(mid >= L) query(k<<1, l, mid, L, R);
if(mid+1 <= R) query((k<<1)+1, mid+1, r, L, R);
}
void change(int k, int l, int r, int val, int pos)//单点修改
{
if(pos>r || pos<l) return;
if(l == r && r == pos)
{
sum[k] = val;
mx[k] = val;
return;
}
int mid = l+r>>1;
if(mid >= pos) change(k<<1, l, mid, val, pos);
if(mid+1 <= pos) change((k<<1)+1, mid+1, r, val, pos);
sum[k] = sum[k<<1]+sum[(k<<1)+1];
mx[k] = max(mx[k<<1], mx[(k<<1)+1]);
}
void dfs1(int u, int f)
{
int v;
size[u] = 1;
fa[u] = f;
dep[u] = dep[f]+1;
for(int i = head[u]; v = e[i].to, i; i = e[i].next)
{
if(v != f)
{
dfs1(v,u);
size[u] += size[v];
if(size[v] > size[son[u]])
son[u] = v;
}
}
}
void dfs2(int u, int f)
{
int v;
if(son[u])
{
seg[son[u]] = ++seg[0];
top[son[u]] = top[u];
rev[seg[0]] = son[u];
dfs2(son[u],u);
}
for(int i = head[u]; v = e[i].to, i; i = e[i].next)
{
if(!top[v])
{
seg[v] = ++seg[0];
rev[seg[0]] = v;
top[v] = v;
dfs2(v,u);
}
}
}
void build(int k, int l, int r)
{
int mid = l+r>>1;
if(l == r)
{
mx[k] = sum[k] = num[rev[l]];
return;
}
build(k<<1, l, mid);
build((k<<1)+1, mid+1, r);
sum[k] = sum[k<<1]+sum[(k<<1)+1];
mx[k] = max(mx[k<<1],mx[(k<<1)+1]);
}
inline int read()
{
char c;
int k = 1;
while((c = getchar())<'0' || c>'9')
if(c == '-') k = -1;
int res = c-'0';
while((c = getchar())>='0' && c<='9')
res = res*10+c-'0';
return res*k;
}
inline void add(int u, int v)
{
e[++cnt].next = head[u];
e[cnt].to = v;
head[u] = cnt;
}
inline void insert(int u, int v)
{
add(u, v);
add(v, u);
}
inline void ask(int u, int v)
{
int fu = top[u], fv = top[v];
while(fu != fv)
{
if(dep[fu]<dep[fv]) swap(u,v), swap(fu,fv);
query(1,1,seg[0],seg[fu],seg[u]);
u = fa[fu], fu = top[u];
}
if(dep[u]>dep[v]) swap(u,v);
query(1,1,seg[0],seg[u],seg[v]);
}
int main()
{
n = read();
for(int i = 1; i < n; i++)
insert(read(),read());
for(int i = 1; i <= n; i++)
num[i] = read();
dfs1(1,0);
seg[0] = seg[1] = rev[1] = top[1] = 1;
dfs2(1,0);
build(1,1,seg[0]);
m = read();
char opt[10];
int u, v;
for(int i = 1; i <= m; i++)
{
scanf("%s",opt+1);
u = read(); v = read();
if(opt[1] == 'C')
change(1,1,seg[0],v,seg[u]);
else
{
summ = 0;
maxx = -0x7fffffff;
ask(u,v);
if(opt[2] == 'M')
printf("%d\n",maxx);
else
printf("%d\n",summ);
}
}
return 0;
}
【luogu P2590 [ZJOI2008]树的统计】 题解的更多相关文章
- Luogu P2590 [ZJOI2008]树的统计
最近在学树剖,看到了这题就做了 [ZJOI2008]树的统计 思路 从题面可以知道,这题是树剖题(要求的和模板没什么区别呀喂 就是在普通的树剖上加了一个最大值 所以可以知道就是树剖+特殊的线段树 线段 ...
- 洛谷P2590 [ZJOI2008]树的统计 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2590 树链剖分模板题. 剖分过程要用到如下7个值: fa[u]:u的父节点编号: dep[u]:u的深度: size[u]: ...
- BZOJ 1036 && Luogu P2590 [ZJOI2008]树的统计 树链剖分
链剖裸题...你值得一做~ 用线段树多维护一个mx,少写一个tag #include<cstdio> #include<iostream> #define ll long lo ...
- [luogu P2590 ZJOI2008] 树的统计 (树链剖分)
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u ...
- Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)
Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...
- P2590 [ZJOI2008]树的统计(树链剖分)
P2590 [ZJOI2008]树的统计 虽然是入门树剖模板 但是我终于1A了(大哭) 懒得写啥了(逃 #include<iostream> #include<cstdio> ...
- [Luogu 2590] ZJOI2008 树的统计
[Luogu 2590] ZJOI2008 树的统计 裸树剖不解释. 比板子还简单. #include <algorithm> #include <cstdio> #inclu ...
- P2590 [ZJOI2008]树的统计(LCT)
P2590 [ZJOI2008]树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把 ...
- 洛谷——P2590 [ZJOI2008]树的统计(树链剖分模板练手)
P2590 [ZJOI2008]树的统计 I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问 ...
随机推荐
- LeetCode 112.路径总和(C++)
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和. 说明: 叶子节点是指没有子节点的节点. 示例: 给定如下二叉树,以及目标和 sum = 22 ...
- Sublime Text加上Eclipse
打造属于自己的前端开发神器 -- 给Sublime Text加上Eclipse的光环 将Sublime Text打造成如Eclipse一般的前端开发IDE 1. 快捷键移植篇 从Java开 ...
- gcc链接非标准(non-standard)命名库
标准命名库: -lnamespace 标准链接库以lib开头, 并以so/a结尾. example gcc test.c -o test -L. -lhello 非标准命名库: -l:libname ...
- 【Linux】linux文件夹打包命令
.tar 解包:tar xvf FileName.tar 打包:tar cvf FileName.tar DirName (注:tar是打包,不是压缩!) ---------------------- ...
- CSS 专业的技巧
目录 专业的技巧 支持情况 贡献准则 专业的技巧 使用CSS复位 继承 box-sizing 使用 :not() 选择器来决定表单是否显示边框 为 body 元素添加行高 垂直居中任何元素 逗号分 ...
- LaTeX 修订
LaTeX多人协同编辑的时候,修订起来与word相比较而言麻烦一些.不过随着技术的发展和需求的增多,会有越来越多的工具支持LaTeX的修订. (1)在线LaTeX ShareLaTeX是一个很优秀的在 ...
- artDialog组件应用学习(四)
一.在对话框自定义操作按钮 预览: html调用代码: var btnArray = [ { value: '同意', callback: function () { this.content('你同 ...
- 01.使用File类读写文件
使用File类去读数据: 方法一:使用ReadAllBytes(); 方法 namespace _01.使用File类读写数据01 { class Program { static void Main ...
- SQLAlchemy的使用---M2M多对多关系
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, Stri ...
- 关于Android那些事
1.开发Activity步骤 第一步:写一个类继承Activity 第二步:重写oncreate方法 第三步:在主配置文件中注册activity <activity android:name=& ...