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 ...
随机推荐
- TeamViewer12.0.71503(远程控制软件)精简版单文件企业版介绍
TeamViewer 是一款能在任何防火墙和 NAT 代理的后台用于远程控制,桌面共享和文件传输的简单且快速的解决方案.为了连接到另一台计算机,只需要在两台计算机上同时运行 TeamViewer 即可 ...
- WinForm------如何跳转另一个窗口,同时关闭当前窗口
添加一个按钮,并为按钮添加点击事件(注:Frm_Main为需要跳转的窗口名字) private void Btn_OK_Click(object sender, EventArgs e) { //打开 ...
- jquery控制滚动条改变上面固定(fixed)导航条或者搜索框的属性
<script type="text/javascript"> $(document).ready(function(){ $(window).scroll( func ...
- Java——文件选择框:JFileChooser
import java.awt.BorderLayout; import java.awt.Container; import java.awt.event.ActionEvent; import j ...
- Java自定义异常类
用户可以根据自己的需要定义自己的异常类,定义异常类只需要继承Exception类即可 //================================================= // Fi ...
- URL组分
url通常包含多个组成部分,在js中可通过location对象获取其中各项信息 访问http://mp.weixin.qq.com/s?__biz=MjM5NjA0NjgyMA==&mid=2 ...
- 安卓官方ViewPager与android.support.design.widget.TabLayout双向交互联动切换 。
该TabLayout的功用,简单的说,就是当用户在该TabLayout的选项卡子item中选择触摸时候,文字和下方的指示器横条滑动指示.android.support.design.widget.Ta ...
- Codeforces 719B Anatoly and Cockroaches(元素的交叉排列问题)
题目链接:http://codeforces.com/problemset/problem/719/B 题目大意: 有一队蟑螂用字符串表示,有黑色 ‘b’ 和红色 'r' 两种颜色,你想使这队蟑螂颜色 ...
- js取float型小数点后两位数的方法
四舍五入以下处理结果会四舍五入:' var num =2.446242342; num = num.toFixed(2); // 输出结果为 2.45 不四舍五入以下处理结果不会四舍五入:第一种, ...
- python 常见排序实例
使用Python 基础排序算法设计,冒泡排序,插入排序,快速排序... 需求 对一组无序数据进行排序算法设计,要求如下: 输入:[1, 3, 5, 23, 75, 34, 456, 86, 22, 7 ...