Description

  一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

  输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

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

Sample Input

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

Sample Output

4
1
2
2
10
6
5
6
5

16

solution:

树链剖分点权模板题。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define inf -1e9
#define ls (t<<1)
#define rs (t<<1)|1
const int maxn = 30010;
int n,no, dfsxu, val[maxn],pos[maxn],head[maxn],heavy[maxn],top[maxn],idx[maxn],dep[maxn],fa[maxn],size[maxn];
struct Edge
{int to, next;
}edge[maxn<<1];
struct segtree
{int l, r, sum,max;
}tree[maxn<<2];
void init()
{no = dfsxu = 0;memset(head, -1, sizeof(head));memset(heavy, 0, sizeof(heavy));dep[1] = fa[1] =size[0]=0;
}
void add(int u, int v)
{edge[no].to = v;edge[no].next = head[u];head[u] = no++;edge[no].to = u;edge[no].next = head[v];head[v] = no++;
}
void dfs(int x)
{size[x] = 1;for (int i = head[x]; ~i; i = edge[i].next){int u = edge[i].to;if (u != fa[x]){fa[u] = x;dep[u] = dep[x] + 1;dfs(u);size[x] += size[u];if (size[heavy[x]] < size[u])heavy[x] = u;}}
}
void spilt(int x, int y)//剖分
{top[x] = y;idx[x] = ++dfsxu;pos[dfsxu] = x;if (heavy[x])spilt(heavy[x], top[x]);for (int i = head[x]; ~i; i = edge[i].next){int u = edge[i].to;if (u != fa[x] && u != heavy[x])spilt(u, u);}
}
void pushup(int t)
{tree[t].max = max(tree[ls].max, tree[rs].max);tree[t].sum = tree[ls].sum + tree[rs].sum;
}
void build(int l, int r, int t)
{tree[t].l = l; tree[t].r = r; tree[t].max = inf; tree[t].sum=0;if (l == r){tree[t].max = tree[t].sum = val[pos[l]];return;}int mid = (l + r) >> 1;build(l, mid,ls);build(mid+1, r, rs);pushup(t);
}
void update(int x, int val, int t)
{if (tree[t].l == x&&tree[t].r == x){tree[t].max = tree[t].sum = val;return;}if (x <= tree[ls].r)update(x, val, ls);else update(x, val, rs);pushup(t);
}
int qqsum(int l, int r, int t)
{if (tree[t].l == l&&tree[t].r == r)return tree[t].sum;if (r <= tree[ls].r)return qqsum(l, r, ls);else if (l >= tree[rs].l)return qqsum(l, r, rs);return qqsum(l, tree[ls].r, ls)+qqsum(tree[rs].l, r, rs);
}
int qsum(int x, int y)
{int ans = 0,u = top[x], v = top[y];while (u != v){if (dep[u] < dep[v]){swap(u, v);swap(x, y);}ans += qqsum(idx[u], idx[x], 1);x = fa[u];u = top[x];}if (dep[x] > dep[y])swap(x, y);ans += qqsum(idx[x], idx[y], 1);return ans;
}
int qqmax(int l, int r, int t)
{if (tree[t].l == l&& tree[t].r == r)return tree[t].max;if (r <= tree[ls].r)return qqmax(l, r, ls);else if (l >= tree[rs].l)return qqmax(l, r, rs);return max(qqmax(l, tree[ls].r, ls), qqmax(tree[rs].l, r, rs));
}
int qmax(int x, int y)
{int ans = inf, u = top[x], v = top[y];while (u != v){if (dep[u] < dep[v]){swap(u, v);swap(x, y);}ans = max(ans,qqmax(idx[u], idx[x], 1));x = fa[u];u = top[x];}if (dep[x] > dep[y])swap(x, y);ans = max(ans,qqmax(idx[x], idx[y], 1));return ans;
}
int main()
{int x,y,q;char op[10];scanf("%d", &n);init();for (int i = 1; i < n; i++){scanf("%d%d", &x, &y);add(x, y);}for (int i = 1; i <= n; i++)scanf("%d", &val[i]);dfs(1);spilt(1, 1);build(1, n, 1);scanf("%d", &q);while (q--){scanf("%s%d%d", op,&x,&y);if (op[0] == 'C')update(idx[x], y, 1);else if (op[1] == 'S')printf("%d\n", qsum(x,y));else printf("%d\n", qmax(x, y));}return 0;
}

bzoj 1036: [ZJOI2008]树的统计Count(树链剖分 点权)相关推荐

  1. bzoj1036: [ZJOI2008]树的统计Count 树链剖分

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

  2. bzoj1036 树的统计Count 树链剖分

    板子题,注意链剖基本写法: sz[o]=1 a<=l&&r<=b op=2 码: #include<iostream> #include<cstdio&g ...

  3. BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3427  Solved: 1429 [Submi ...

  4. 树链剖分(bzoj 1036: [ZJOI2008]树的统计Count)

    树链剖分: 把一棵树剖分为若干条链,然后利用数据结构(树状数组,SBT,Splay,线段树等等)去维护每一条链,复杂度 为O(logn),总体复杂度O(nlog²n) 步骤: ①将树的边分成重边和轻边 ...

  5. [ZJOI2008][BZOJ1036] 树的统计count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 7980  Solved: 3266 [Submi ...

  6. 树链剖分入门+HYSBZ - 1036树的统计Count

    今天学习了树链剖分,记录一下. [题目背景] HYSBZ - 1036树的统计Count [题目分析] 题目要求求任意结点之间路径的和以及路径上最大的结点,还有可能修改.如果正常做可能会很复杂(我也不 ...

  7. BZOJ1036: [ZJOI2008]树的统计Count

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

  8. 【BZOJ 1036】[ZJOI2008]树的统计Count

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 [题意] [题解] 树链剖分入门题; 每一条链维护一个线段树就好; uppest ...

  9. BZOJ 1036 [ZJOI2008]树的统计Count

    以前动态树写过这个题,今天尝试树链剖分解决~ 模板题,就声明一点,线段树维护的是点权 View Code 1 #include <iostream> 2 #include <cstd ...

  10. 树链剖分 - BZOJ 1036: [ZJOI2008]树的统计Count

    这是树链剖分的入门题,也是我学树链剖分的第一题. 树链剖分:就是把树中和线段树联系起来,求(u,v)路径中权值的最大值和其路径的权值和. 入门blog:http://blog.sina.com.cn/ ...

最新文章

  1. 【OpenCV 4开发详解】图像直方图绘制
  2. 洛谷3605 Promotion Counting
  3. 学习ESLint的规则配置,ESLint语法检测配置说明
  4. 小米12 Ultra有望换装索尼传感器:牵手徕卡 搭载新一代影像旗舰
  5. 【.NET类库】通过SharpSocket进行TCP/UDP通信数据传输
  6. 隐马尔科夫模型(HMM)详解
  7. 常用验证码功能实现大全
  8. 我的Android进阶之旅------Android中编解码学习笔记
  9. JAVA爬虫--编写第一个网络爬虫程序
  10. python图像拼接_图像拼接_图像拼接算法_python图像拼接 - 云+社区 - 腾讯云
  11. java邮件客户端_java实现POP3邮件客户端
  12. 软件开发中的十大困难
  13. Mumble安装部署教程
  14. office文件转换为pdf文件
  15. 服务器10的系统杀毒怎么关,Win10自带杀毒软件怎么关闭?彻底关闭Windows Defender方法...
  16. 录屏储存失败因为5823_屏幕录制存储失败因为5823
  17. 基于BES+DSP 的音频系统方案设计
  18. 广州楼市:这类楼盘持续跑赢大势,聪明人只看这点
  19. Chrome浏览器查看网页源代码的几种方法
  20. 已经清空了垃圾箱怎样找回误删的文件

热门文章

  1. 测试用例设计方法——等价类划分法
  2. idea格式化代码快捷键
  3. 【辅助开发】游戏辅助开发全流程-golang
  4. Git 小乌龟(TortoiseGit)的详细使用
  5. 数字通信学习笔记——自相关函数、随机信号
  6. smith圆图重要性_smith圆图的理解
  7. 飞思卡尔单片机学习记录(一)
  8. 如何删除电脑里的android驱动程序,驱动安装失败 如何手动清除旧驱动程序
  9. 《机器学习算法竞赛实战》读书笔记
  10. 图书管理系统的结构流程图