BZOJ1036——树的统计count
1、题目大意:给你一棵树,有三种操作
1>qmax,询问u到v中间点权的最大值
2>qsum,询问u到v中间点权和
3>change,把u这个节点的权值改为v
2、分析:树链剖分的裸题,搞了一个礼拜。。。
需要维护的东西
1>height[x] x的深度
2>Top[x] x所在树链的最顶端
3>num[x] x在线段树的标号
4>father[x] x的父亲
5>size[x] 以x为根的字数的节点数
6>value[x] x的权值
7>segment_tree
哪个儿子的size最大,那么连着这个儿子的边就是重边
然后比如求点权最大值,然后就让Top值最大的那个点往上跳到father[Top[这个点]],更新ret,直到u和v是同一个链上的
线段树就搞一搞,求和也是类似的,修改就是线段树单点的修改
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
struct segment_tree{
int q[1001000];
int sum[1001000];
int x, y;
void init(){
for(int i = 1; i <= 1000000; i ++) q[i] = -2147483647;
return;
}
void add(int l, int r, int o){
if(l == r && x == l){
sum[o] = q[o] = y;
return;
}
int mid = (l + r) / 2;
if(x <= mid) add(l, mid, 2 * o);
if(x > mid) add(mid + 1, r, 2 * o + 1);
q[o] = max(q[2 * o], q[2 * o + 1]);
sum[o] = sum[2 * o] + sum[2 * o + 1];
return;
}
int query_max(int l, int r, int o){
if(x <= l && r <= y){
return q[o];
}
int mid = (l + r) / 2;
int ret = -2147483647;
if(x <= mid) ret = max(ret, query_max(l, mid, 2 * o));
if(y > mid) ret = max(ret, query_max(mid + 1, r, 2 * o + 1));
return ret;
}
int query_sum(int l, int r, int o){
if(x <= l && r <= y){
return sum[o];
}
int mid = (l + r) / 2;
int ret = 0;
if(x <= mid) ret += query_sum(l, mid, 2 * o);
if(y > mid) ret += query_sum(mid + 1, r, 2 * o + 1);
return ret;
}
} qzh;
struct node{
int from, to, next;
};
struct tree_chain_partition{
int Top[1000100];
int Size[1000100];
int height[1000100];
int father[1000100];
int num[1000100];
int value[1000100];
node G[1000100];
int head[1000100];
int ff;
int de;
int n;
void init(){
memset(head, -1, sizeof(head));
ff = -1;
return;
}
void insert(int u, int v){
ff ++;
G[ff] = (node){u, v, head[u]};
head[u] = ff;
return;
}
void dfs1(int x, int fa, int k){
father[x] = fa;
height[x] = k;
Size[x] = 1;
for(int i = head[x]; i != -1; i = G[i].next){
node e = G[i];
if(e.to != fa){
dfs1(e.to, x, k + 1);
Size[x] += Size[e.to];
}
}
return;
}
void dfs2(int x, int fa){
int o = 0, pos;
for(int i = head[x]; i != -1; i = G[i].next){
node e = G[i];
if(Size[e.to] > o && e.to != fa){
pos = i;
o = Size[e.to];
}
}
if(o != 0){
qzh.x = ++ de;
qzh.y = value[G[pos].to];
qzh.add(1, n, 1);
num[G[pos].to] = de;
Top[G[pos].to] = Top[x];
dfs2(G[pos].to, x);
}
for(int i = head[x]; i != -1; i = G[i].next){
node e = G[i];
if(e.to != fa && i != pos){
qzh.x = ++ de;
qzh.y = value[e.to];
qzh.add(1, n, 1);
num[e.to] = de;
Top[e.to] = e.to;
dfs2(e.to, x);
}
}
return;
}
void solve(){
qzh.init();
dfs1(1, 0, 1);
qzh.x = ++ de;
qzh.y = value[1];
qzh.add(1, n, 1);
num[1] = de;
Top[1] = 1;
dfs2(1, 0);
return;
}
void change(int s, int t){
qzh.x = num[s];
qzh.y = t;
qzh.add(1, n, 1);
return;
}
int qmax(int s, int t){
int ret = -2147483647;
while(Top[s] != Top[t]){
if(height[Top[s]] > height[Top[t]]) swap(s, t);
qzh.x = num[Top[t]];
qzh.y = num[t];
ret = max(ret, qzh.query_max(1, n, 1));
t = father[Top[t]];
}
if(height[s] > height[t]) swap(s, t);
qzh.x = num[s];
qzh.y = num[t];
ret = max(ret, qzh.query_max(1, n, 1));
return ret;
}
int qsum(int s, int t){
int ret = 0;
while(Top[s] != Top[t]){
if(height[Top[s]] > height[Top[t]]) swap(s, t);
qzh.x = num[Top[t]];
qzh.y = num[t];
ret += qzh.query_sum(1, n, 1);
t = father[Top[t]];
}
if(height[s] > height[t]) swap(s, t);
qzh.x = num[s];
qzh.y = num[t];
ret += qzh.query_sum(1, n, 1);
return ret;
}
} wt;
int main(){
wt.init();
scanf("%d", &wt.n);
for(int i = 1; i < wt.n; i ++){
int u, v;
scanf("%d%d", &u, &v);
wt.insert(u, v);
wt.insert(v, u);
}
for(int i = 1; i <= wt.n; i ++) scanf("%d", &wt.value[i]);
int q;
scanf("%d", &q);
wt.solve();
while(q --){
char str[10];
int u, v;
scanf("%s%d%d", str, &u, &v);
if(str[1] == 'H') wt.change(u, v);
else if(str[1] == 'M') printf("%d\n", wt.qmax(u, v));
else printf("%d\n", wt.qsum(u, v));
}
return 0;
}
BZOJ1036——树的统计count的更多相关文章
- BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)
潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...
- bzoj1036 树的统计Count
第一次写链剖,于是挑了个简单的裸题写. 以下几点要注意: 1.链剖中的height是从根到该店经过的轻边个数 2.分清num与sum..... #include<cstdio> #incl ...
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
[BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...
- [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分
树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...
- bzoj1036 [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MB Submit: 12646 Solved: 5085 [Subm ...
- bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题
[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...
- bzoj千题计划124:bzoj1036: [ZJOI2008]树的统计Count
http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分板子题 #include<cstdio> #include<iost ...
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14302 Solved: 5779[Submit ...
- BZOJ 1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MB Submit: 14354 Solved: 5802 [Subm ...
随机推荐
- 利用WSCF进行契约先行的Web Services开发
http://www.cnblogs.com/goody9807/archive/2007/06/05/772107.html 什么是契约先行(Contract-First)? 如果说一个新的软件开发 ...
- C#实现录制屏幕
以前写过两篇录制麦克风语音和摄像头视频的文章(实现语音视频录制.在服务器端录制语音视频),最近有朋友问,如果要实现屏幕录制这样的功能,该怎么做了?实际上原理是差不多的,如果了解了我前面两篇文章中介绍的 ...
- ubuntu删除输入法后,循环登陆
在登陆界面ctrl+alt+F1进入tty界面,登陆账号,然后输入 dpkg -l |grep ^rc|awk '{print $2}' |sudo xargs dpkg -P 可以参考Ubuntu1 ...
- JSP 原理
参考文献:http://www.cnblogs.com/xdp-gacl/p/3764991.html 一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都 ...
- PyCharm 教程(四)显示行号
PyCharm 教程(四)显示行号 在PyCharm 里,显示行号有两种办法: 1,临时设置.右键单击行号处,选择 Show Line Numbers. 但是这种方法,只对一个文件有效,并且,重启Py ...
- Redis学习——链表源码分析
0. 前言 Redis 中的链表是以通用链表的形式实现的,而对于链表的用途来说,主要的功能就是增删改查,所以对于查找来说,redis其提供了一个match函数指针,用户负责实现其具体的匹配操作,从而实 ...
- ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase玩转URL
http://www.cnblogs.com/John-Connor/archive/2012/05/03/2478821.html 引言-- 在初级篇中,我们介绍了如何利用基于ASP.NET MVC ...
- Xcode常用技巧(1)-使用Xcode进行代码分析及GDB调试
1. 使用Xcode分析代码,分析分为静态分析及动态分析 静态分析:(Xcode-Product-Analyze) 检测代码是否有潜在的内存泄露 编译器认为不太合适的代码 运行结果: 若程序有 ...
- android自定义控件(1)-点击实现开关按钮切换
自定义控件的步骤.用到的主要方法: 1.首先需要定义一个类,继承自View:对于继承View的类,会需要实现至少一个构造方法:实际上这里一共有三个构造方法: public View (Contex ...
- XSHELL下直接下载文件到本地(Windows)
xshell很好用,然后有时候想在windows和linux上传或下载某个文件,其实有个很简单的方法就是rz,sz 首先你的Ubuntu需要安装rz.sz(如果没有安装请执行以下命令,安装完的请跳过. ...