树的统计

金牌导航 树链剖分-1

题目大意

给出一棵树,让你做若干操作,操作如下:
1.修改一个节点的值
2.查询两个节点之间路径的最大值
3.查询两个节点之间路径的和

输入样例

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

输出样例

4
1
2
2
10
6
5
6
5
16

数据范围

1⩽N⩽3×104,0⩽q⩽2×105,−3×104⩽si⩽3×1041\leqslant N\leqslant 3\times 10^4,0\leqslant q\leqslant 2\times10^5,-3\times 10^4\leqslant s_i\leqslant 3\times 10^41⩽N⩽3×104,0⩽q⩽2×105,−3×104⩽si​⩽3×104

解题思路

树链剖分,然后用线段树维护重链,每个节点维护最大值和权值和

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 30030
using namespace std;
int n, m, x, y, w, tot, ansmax, anssum;
int a[N], s[N<<4], v[N], fa[N], hs[N], han[N], dfn[N], dep[N], size[N], head[N], maxx[N<<4];
string str;
struct rec
{int to, next;
}e[N<<1];
void add(int x, int y)
{e[++tot].to = y;e[tot].next = head[x];head[x] = tot;
}
void dfs1(int x)//找重儿子
{size[x] = 1;for (int i = head[x]; i; i = e[i].next)if (e[i].to != fa[x]){fa[e[i].to] = x;dep[e[i].to] = dep[x] + 1;dfs1(e[i].to);size[x] += size[e[i].to];if (size[e[i].to] > size[hs[x]]) hs[x] = e[i].to;}return;
}
void dfs2(int x)
{dfn[x] = ++w;v[w] = x;if (hs[x]){han[hs[x]] = han[x];//重祖先dfs2(hs[x]);}for (int i = head[x]; i; i = e[i].next)if (e[i].to != fa[x] && e[i].to != hs[x]){han[e[i].to] = e[i].to;dfs2(e[i].to);}
}
void up(int x)
{s[x] = s[x * 2] + s[x * 2 + 1];maxx[x] = max(maxx[x * 2], maxx[x * 2 + 1]);return;
}
void build(int now, int l, int r)//线段树维护
{if (l == r){maxx[now] = s[now] = a[v[l]];return;}int mid = (l + r) >> 1;build(now * 2, l, mid);build(now * 2 + 1, mid + 1, r);up(now);return;
}
void change(int x, int y, int now, int l, int r)
{if (l == r){maxx[now] = s[now] = y;return;}int mid = (l + r) >> 1;if (x <= mid) change(x, y, now * 2, l, mid);else change(x, y, now * 2 + 1, mid + 1, r);up(now);return;
}
void ask(int now, int ql, int qr, int l, int r)
{if (l == ql && r == qr){ansmax = max(ansmax, maxx[now]);anssum += s[now];return;}int mid = (l + r) >> 1;if (qr <= mid) {ask(now * 2, ql, qr, l, mid); return;}if (ql > mid) {ask(now * 2 + 1, ql, qr, mid + 1, r); return;}ask(now * 2, ql, mid, l, mid);ask(now * 2 + 1, mid + 1, qr, mid + 1, r);return;
}
void askk(int x, int y)//计算路径长度
{anssum = 0;ansmax = -N;while(han[x] != han[y]){if (dep[han[x]] < dep[han[y]]) swap(x, y);ask(1, dfn[han[x]], dfn[x], 1, n);x = fa[han[x]];}if (dep[x] < dep[y]) swap(x, y);ask(1, dfn[y], dfn[x], 1, n);return;
}
int main()
{scanf("%d", &n);for (int i = 1; i < n; ++i){scanf("%d%d", &x, &y);add(x, y);add(y, x);}for (int i = 1; i <= n; ++i)scanf("%d", &a[i]);fa[1] = 1;han[1] = 1;dfs1(1);dfs2(1);build(1, 1, n);scanf("%d", &m);while(m--){cin>>str;scanf("%d%d", &x, &y);if (str == "CHANGE"){change(dfn[x], y, 1, 1, n);}else{askk(x, y);if (str == "QSUM") printf("%d\n", anssum);else if (str == "QMAX") printf("%d\n", ansmax);}}return 0;
}

【树链剖分】【线段树】树的统计(金牌导航 树链剖分-1)相关推荐

  1. 【树链剖分】染色(luogu 2486/金牌导航 树链剖分-3)

    正题 luogu 2486 金牌导航 树链剖分-3 题目大意 给你一棵树,让你进行以下操作: 1.把一条路径染上一个颜色 2.查询一条路径上有多少个颜色段 解题思路 用树链剖分把问题转化为链上问题 然 ...

  2. 【树链剖分】软件管理(luogu 2146/金牌导航 树链剖分-2)

    正题 luogu 2146 金牌导航 树链剖分-2 题目大意 有若干软件,除了软件0,所有软件都依赖且只依赖于另外一个软件 当要删除一个软件时,所有依赖于该软件的软件都要删掉 当安装一个软件时,该软件 ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 1153  Solved: 421 [Submit][Sta ...

  4. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  5. CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...

  6. CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...

  7. SPOJ - QTREE Query on a tree(树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一棵由n个点组成的树,再给出数个操作,每次操作分为下列几种类型: QUERY x y:询问点x-点y这条路径上的所有边权的最大值 CHANGE x y:将第x条边的权 ...

  8. HDU - 3804 Query on a tree(树链剖分+线段树+离线处理)

    题目链接:点击查看 题目大意:给出一棵树,每条边上都有一个权值,给出m个查询:a,b:问从点1到点a的唯一路径上,在边权小于等于b的边中选出边权最大的值输出,若没有符合条件的边则输出-1: 题目分析: ...

  9. P2486 [SDOI2011]染色(树链剖分+线段树)

    题干描述 输入描述 输出格式 对于每个询问操作,输出一行答案. 输入输出样例 输入 #1 复制 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q ...

最新文章

  1. CodeGen结构循环回路
  2. OpenCV Mat类详解
  3. 用户自助查看kubectl使用的证书状态以及如何更新
  4. 电子网络发票应用系统网络不通_深度强化学习在典型网络系统中的应用综述
  5. vue组件的通信方式
  6. MySQL高可用--MGR入门(4)异常恢复
  7. nginx限速方法以及报错处理
  8. 实例篇——springboot自定义拦截器
  9. 架构师必备!java架构师资格证书
  10. 辛弃疾最经典的10首词
  11. 【陈曲写作】考研英语写作
  12. 【计算机视觉】数字图像处理(六)—— 图像压缩
  13. jenkins邮件配置和邮件发送
  14. dataframe交换某两行(多行)的数据
  15. 惠普服务器开机系统密码,惠普(hp)各型号打印机冷复位,清零,回复出厂设置方法 以及 服务菜单(service menu)密码...
  16. TwinCAT3常见问题1
  17. TeX/LaTeX相关软件
  18. js获取不到模板DOM元素
  19. Python学习-8.2 库(第三方库介绍与下载安装)
  20. 2021应届毕业生该何去何从?

热门文章

  1. python中list的意思_list在python中是什么意思
  2. linux环境下创建postgis数据库,linux下搭建postgresql、postgis、pg_pathman环境步骤详解...
  3. categories php,manage-categories.php
  4. 过去3个多月的1200个小时里,我收获了什么?| 2021年年中总结
  5. [Java基础]字符串中的编码解码问题
  6. 蓝桥杯2016初赛-有奖猜谜-模拟
  7. SQL(八)- python执行SQL语句
  8. 6-7 求链表的倒数第m个元素 (25 分)
  9. Java LinkedList双向链表源码分析
  10. uoj#422. 【集训队作业2018】小Z的礼物