bzoj1036点权模板题
/*
HYSBZ1036
树上有1-n个结点,每个节点都有一个权值w
操作 CHANGE u t:把结点u的权值改为t
QMAX u v:询问从点u到v的路径上的节点的最大权值
QSUM u v:询问从点u到v的路径上的结点的权值和
从点u到点v路径上的结点包括u,v本身 */
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MAXN 30010
using namespace std;
struct Edge{
int to, next;
}edge[MAXN*];
int head[MAXN], tot;
int top[MAXN];//重链顶端
int fa[MAXN];//父亲
int deep[MAXN];//深度,root=1
int num[MAXN];//子节点数
int p[MAXN];//v在线段树中的位置
int fp[MAXN];
int son[MAXN];//重儿子
int pos;
void init(){
tot = ;
memset(head, -, sizeof(head));
pos = ;
memset(son, -, sizeof(son));
}
void addedge(int u, int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
//第一次dfs求fa,deep,son,num
void dfs1(int u, int pre, int d){
deep[u] = d;
fa[u] = pre;
num[u] = ;
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;
if (v != pre){
dfs1(v, u, d+);
num[u]+=num[v];
if (son[u]==-||num[v]>num[son[u]])
son[u] = v;
}
}
}
//第二次dfs求top,p,用pos记数
void getpos(int u, int sp){//sp表示重链顶端
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if (son[u]==-)
return;
getpos(son[u], sp);//先把重儿子查到底
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;//轻儿子
if (v != son[u] && v != fa[u])
getpos(v, v);
}
} //线段树部分
struct Node{
int l, r;
int sum;
int Max;
}segTree[MAXN*];
inline void push_up(int i){
segTree[i].sum = segTree[i<<].sum + segTree[i<<|].sum;
segTree[i].Max = max(segTree[i<<].Max, segTree[i<<|].Max);
}
int s[MAXN];
void build(int i, int l, int r){
segTree[i].l = l;
segTree[i].r = r; if (l==r){
segTree[i].sum = segTree[i].Max = s[fp[l]];
return;
} int mid = l+r >> ;
build(i<<, l, mid);
build(i<<|, mid+, r);
push_up(i);
}
//更新线段树的第k个值为val
void update(int i, int k, int val){
if(segTree[i].l == k && segTree[i].r == k){
segTree[i].Max = segTree[i].sum = val;
return;
}
int mid = segTree[i].l + segTree[i].r >> ;
if (k <= mid)
update(i<<, k, val);
else
update(i<<|, k, val);
push_up(i);//单点更新后要重新计算Max和Sum
}
//查询[l,r]区间的最大值
int queryMax(int i, int l, int r){
if(segTree[i].l == l && segTree[i].r == r)
return segTree[i].Max;
int mid = segTree[i].l+segTree[i].r >> ;
if (r <= mid)
return queryMax(i<<, l, r);
else if (l > mid)
return queryMax(i<<|, l, r);
else
return max(queryMax(i<<, l, mid), queryMax(i<<|, mid+, r));
}
//查询[l,r]区间的和
int querySum(int i, int l, int r){
if(segTree[i].l==l && segTree[i].r == r)
return segTree[i].sum;
int mid = segTree[i].l+segTree[i].r>>;
if(r <= mid)
return querySum(i<<,l,r);
else if(l > mid)
return querySum((i<<)|,l,r);
else
return querySum(i<<, l, mid)+querySum(i<<|, mid+, r);
}
//查询u->v路径上结点的最大权值
int findMax(int u, int v){
int f1 = top[u], f2 = top[v];
int tmp = -;
while(f1!=f2){//不在同一条重链上时
if(deep[f1]<deep[f2]){
swap(u, v);
swap(f1, f2);
}
tmp = max(tmp, queryMax(, p[f1], p[u]));//把这一条链上的求出来
u = fa[f1];
f1 = top[u];
}
if (deep[u]>deep[v])
swap(u,v);
return
max(tmp, queryMax(, p[u], p[v])); }
//查询u->v路径上结点的权值
int findSum(int u, int v){
int f1 = top[u];
int f2 = top[v];
int tmp = ;
while(f1 != f2){
if (deep[f1] < deep[f2]){
swap(f1, f2);
swap(u, v);
}
tmp += querySum(, p[f1], p[u]);
u = fa[f1];
f1 = top[u];
}
if(deep[u]>deep[v])
swap(u, v);
return tmp + querySum(, p[u], p[v]);
} int main(){
int n;
int q;
char op[];
int u, v;
while(scanf("%d", &n)==){
init();
for(int i = ; i < n; i++){
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
for(int i = ; i <= n; i++)
scanf("%d", &s[i]); dfs1(,,);
getpos(,);
build(, , pos-); scanf("%d", &q);
while(q--){
scanf("%s%d%d", op, &u, &v);
if (op[]=='C')
update(, p[u], v);//单点修改
else if (strcmp(op, "QMAX")==)
printf("%d\n", findMax(u, v));//查询u->v路径上点权的最大值
else
printf("%d\n", findSum(u, v));//查询路径上点权的和
}
}
return ;
}
bzoj1036点权模板题的更多相关文章
- EOJ Monthly 2018.8 D. Delivery Service-树上差分(边权/边覆盖)(边权转点权)(模板题)
D. Delivery Service 单测试点时限: 2.5 秒 内存限制: 512 MB EOJ Delivery Service Company handles a massive amount ...
- bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题
[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...
- 洛谷 P3128 [USACO15DEC]最大流Max Flow-树上差分(点权/点覆盖)(模板题)
因为徐州现场赛的G是树上差分+组合数学,但是比赛的时候没有写出来(自闭),背锅. 会差分数组但是不会树上差分,然后就学了一下. 看了一些东西之后,对树上差分写一点个人的理解: 首先要知道在树上,两点之 ...
- 【BZOJ1036】[ZJOI2008] 树的统计Count(一道可怕的模板题:树剖+线段树)
点此看题面 题解 这真的只是一道模板题:一个树链剖分套上一个线段树(令我窒息的组合). 既然是模板题,那就直接上代码吧. 代码 #include<bits/stdc++.h> #defin ...
- [置顶] 小白学习KM算法详细总结--附上模板题hdu2255
KM算法是基于匈牙利算法求最大或最小权值的完备匹配 关于KM不知道看了多久,每次都不能完全理解,今天花了很久的时间做个总结,归纳以及结合别人的总结给出自己的理解,希望自己以后来看能一目了然,也希望对刚 ...
- 【最大流ISAP】洛谷P3376模板题
题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...
- POJ - 3264 线段树模板题 询问区间最大最小值
这是线段树的一个模板题,给出一串数字,然后询问区间的最大最小值. 这个其实很好办,只需把线段树的节点给出两个权值,一个是区间的最小值,一个是区间的最大值,初始化为负无穷和正无穷,然后通过不断地输入节点 ...
- HDU 3966 Aragorn's Story(模板题)【树链剖分】+【线段树】
<题目链接> 题目大意: 给定一颗带点权的树,进行两种操作,一是给定树上一段路径,对其上每个点的点权增加或者减少一个数,二是对某个编号点的点权进行查询. 解题分析: 树链剖分的模板题,还不 ...
- P1339 热浪 最短路径模板题
这么naive的题面一看就是最短路模板题~~~ ok.首先是floyd算法,tts,记得把k放在最外面就行了. #include <cstdio> #include <cstring ...
随机推荐
- Eclipse启动时出现错误 An internal error occurred during: "Updating indexes"
在Eclipse的workspace下有个.metadata文件夹,Eclipse出现异常的log文件就在这个目录下. 最近出现了这样的错误: 查看日志文件发现: !ENTRY org.ecl ...
- 4、JDBC-API
访问数据库 /** * 在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式: * * Statement * * PrepatedStatement * * CallableS ...
- 学习windows编程 day4 之 设置画刷
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRU ...
- .NET Framework自带的文件内存映射类
最近一直为文件内存映射发愁,整个两周一直折腾这个东西.在64位系统和32位系统还要针对内存的高低位进行计算.好麻烦..还是没搞定 偶然从MSDN上发现.NET 4.0把内存文件映射加到了.NET类库中 ...
- 转--python 编码规范
编程规范 1.1. 命名规范 1.1.1. [强制] 命名不能以下划线或美元符号开始和结尾 反例: name / __name / $Object / name / name$ / Object$ 1 ...
- 基于Redis主从复制读写分离架构的Session共享(Windows Server)
搭建主从复制 1.安装软件 下载Redis-x64-3.2.100.zip:https://github.com/MicrosoftArchive/redis/releases 第一步:将Redis拷 ...
- Python中的包ImportError
前言 Python中的包给我提供了很好的代码组织,相似的功能模块放在同一个包内,不仅代码结构清晰,而且调用起来也比较方便(可以用*导入) 但是,我们在刚开始使用Python包的时候总是会遇到导入错误& ...
- android 简单的读写联系人
一.读取联系人 (1).从raw_contact表读 contact_id (2).从data表中读取data1 (3).从mimetypes读取mimetype 1.AndroidManifest. ...
- 第19月第8天 斯坦福大学公开课机器学习 (吴恩达 Andrew Ng)
1.斯坦福大学公开课机器学习 (吴恩达 Andrew Ng) http://open.163.com/special/opencourse/machinelearning.html 笔记 http:/ ...
- printf 函数的实现原理
/* * ===================================================================================== * * Filen ...