树链剖分

hdu 3966 树链剖分

断了今生、忘了曾经 提交于 2019-12-01 10:22:27
树链剖分模板题目,记录一下。 总结: 这里我re了 几次,在于update操作中,应该先判断头节点的深度,优先跳转深度浅的,而不是判断当前两个点那个更深,这是没有意义的。 这里son可以memset成-1,因为dfs的时候会优先赋值不会存在数组越界。 head数组也需要复制-1。 其余数组在两次dfs中会被依次赋值,再多组输入中不用重复清空,会自动覆盖掉上次结果。 #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<climits> #include<stack> #include<vector> #include<queue> #include<set> #include<map> //#include<regex> #include<cstdio> #define up(i,a,b) for(int i=a;i<b;i++) #define dw(i,a,b) for(int i=a;i>b;i--) #define upd(i,a,b) for(int i=a;i<=b;i++) #define dwd(i,a,b) for(int i=a;i>=b;i--) //#define local typedef long long

P3384 【模板】树链剖分

血红的双手。 提交于 2019-12-01 06:17:34
#include<bits/stdc++.h> // #include<iostream> // #include<stdio.h> // #include<iomanip> // #include<stack> // #include<queue> // #include<algorithm> // #include<cstring> // #include<map> // #include<vector> // #include<numeric> // #include<iterator> // #include<cmath> #define met(a,x) memset(a,x,sizeof(a)); #define lowbit(x) (x&(-x)) #define mid ((l + r) >> 1) #define len (r - l + 1) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 using namespace std; int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); } int lcm(int a, int b) { return a * b / gcd(a, b); } typedef long long ll;

简述树链剖分

青春壹個敷衍的年華 提交于 2019-12-01 05:23:15
目录 前置知识 预处理 维护 查询 子树有关操作 子树查询 子树修改 树链有关操作 链查询 链修改 @(简述树链剖分) 题目链接: luogu P3384 【模板】树链剖分 先上完整代码,变量名解释 1 #include<cstdio> #include<algorithm> #include<iostream> using namespace std; typedef long long ll; #define N 500005 #define RI register int int tot=0,n,m,rt,md; int fa[ N ],deep[ N ],head[ N ],size[ N ],son[ N ],id[ N ],w[ N ],nw[ N ],top[ N ]; struct EDGE{ int to,next; }e[ N ]; inline void add( int from , int to ){ e[ ++ tot ].to = to; e[ tot ].next = head[ from ]; head[ from ] = tot; } template<class T> inline void read(T &res){ static char ch;T flag = 1; while( ( ch = getchar() ) < '0' ||

树链剖分

前提是你 提交于 2019-12-01 04:52:44
      树链剖分的概念:          树链剖分(重链剖分),是处理树上极值、权值和问题,支持修改和查询的一种数据结构。     主体思路:1、通过轻重边剖分将树分割成多条链;          2、再利用线段树、主席树等数据结构来维护这些链上的信息。     所以我们可以说树链剖分本质上是一种优化暴力。       树链剖分的要素:        重儿子:父亲节点的所有儿子中子树结点数目最多(size最大)的结点;     轻儿子:父亲节点中除了重儿子以外的儿子;     重边:父亲结点和重儿子连成的边;     轻边:父亲节点和轻儿子连成的边;     重链:由多条重边连接而成的路径;      轻链:由多条轻边连接而成的路径;         如图所示: 图中数字为每个节点的子树规模,粗边为重链, 我们称某条路径为重链,当且仅当它全部由重边组成        树链剖分的性质:       1、所有重链互不相交,即每个点只属于一条重链     2、所有重链长度和等于节点数     3、一个点到根节点的路径上经过的边中轻边最多只有log条     一 、二两性质由上图易得。     关于第三个性质,考虑 最坏情况,令这个点到根路径上经过的边都是轻边。     那么每经过一条轻边到达这个点的父亲节点时,就代表着这个父亲节点至少还有一个与当前子树同样规模的子树,    

HDU-6547 Tree (树链剖分,线段树区间开根号)

折月煮酒 提交于 2019-12-01 02:41:36
题目链接: HDU-6547 Tree 题意 wls 有三棵树,树上每个节点都有一个值 $a_i$ ,现在有 2 种操作: 1. 将一条链上的所有节点的值开根号向下取整; 2. 求一条链上值的和; 链的定义是两点之间的最短路。 思路 树链剖分裸题,区间开根号可用线段树做,利用 $10^9$ 范围内的数经过少数几次开根号之后就会达到 1,标记线段树区间最大值,若为 1 则无需再往下更新。 树链剖分传送门: https://www.cnblogs.com/kangkang-/p/8486150.html 代码实现 #include <stdio.h> #include <iostream> #include <cmath> #define REP(i, a, b) for (int i = a; i <= b; i++) using namespace std; typedef long long LL; const double esp = 1e-8; const int MAXN = 110000; struct Node { int to, next; } edg[MAXN<<1]; struct segmentTree { int left, right; LL sum, maxx; } tree[MAXN<<2]; int head[MAXN], siz[MAXN], top

树链剖分

拥有回忆 提交于 2019-11-30 12:26:46
自从漫长暑假的两次培训由于某些原因就再没整理过博客 仔细分析一下qbxt的教学模式已经内容,无非就是讲知识点,讲题目罢了,而且为了赶进度,速度也非常快 那么把qbxt整理博客拆分成若干的知识整理博客以及题目整理博客,而非以往的单纯罗列知识点的,对于那些难题写一写口胡思路但是对其算法没有进行实现,甚至不了解该算法的"八股博客"(我只是在说我自己的),两者相比学习效果要差太多了 所以以后的博客整理将侧重知识点的梳理,而非罗列我本身也尽量避免"八股"的出现, 做到言之有物,整之有理,观之有效 我尽量8 好,废话不再说一些(临沂口音) 树剖 前置芝士: 树的基本操作(邻接表,树上dfs啥的), 基本的 线段树 (要求充分理解并熟练掌握), LCA 基本思路(理解为什么要选尽量深的节点跳) 后两个不懂的我博客都有哈! 一些问题: 树剖是啥? 废话,树链剖分 树剖就是通过某种算法对树上信息进行整理,使树上的查询更加方便的算法 树剖的具体目的? 主体思路是将树拆分成有着某种特定性质的区间,使得这个(或这些)区间可以利用数据结构进行处理,以实现用数据结构进行树上信息维护和查询 怎么实现? 急嘛?这篇博客就是要讲这个啊?! 正文: 下面来讲理论以及实现方式 首先入门需要知道这样几个变量: 第一组: int fa[N],son[N],dep[N],size[N]; fa[]的意义很明确

[BZOJ4712]洪水(树链剖分+DP)

て烟熏妆下的殇ゞ 提交于 2019-11-30 12:07:35
题意 给一颗点带权的树,删除一个点需要花费对应的代价,每次询问一颗子树,求最小代价,使得子树的根到不了子树中的任何叶子,支持将单点的权值增加一个正值 思路 设 \(f[i]\) 表示i子树的答案,h[i]表示i的所有儿子的f和,w[i]表示i的权值,不难列出状态转移方程: f[i]=min(w[i],h[i]) 如果i是叶子,就将它的h赋成正无穷,可以避免一些讨论 对于修改操作,由于w只会增加,所以各个数组的值都不会减少 一个显然的情况是,如果一个点的f值已经等于w,那么无论它的h怎么增加,它的f值是不会变的(除非修改它的w) 设修改过程中的某个点的f值变化了delta,我们将该点对祖先的影响分为四种情况(设该点为i,父亲为fa) \(delta=0\) ,那么它的祖先不会变,break(其实和2差不多) \(f[fa]==w[fa]\) ,即修改它的h值对f没有影响,h[fa]+=delta,delta=0,下一步就会break掉 \(w[fa]>h[fa],w[fa]>h[fa]+delta\) ,即加了delta之后,f[fa]也会加delta \(w[fa]>f[fa],w[fa]\leq h[fa]+delta\) ,即加了delta之后,f[fa]就变为w[fa] 用树链剖分维护min(w-h),h,对于修改操作,找到最上面的满足3的点,将这一段路径的h值加delta

POJ-3237:Tree(树链剖分)

人走茶凉 提交于 2019-11-30 10:04:17
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 10785 Accepted: 2800 Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms: CHANGE i v Change the weight of the i th edge to v NEGATE a b Negate the weight of every edge on the path from a to b QUERY a b Find the maximum weight of edges on the path from a to b Input The input contains multiple test

树链剖分

ぐ巨炮叔叔 提交于 2019-11-30 06:10:16
树链剖分 强烈安利一个 树链剖分入门讲解代码 (手动感谢这位神仙QWQ,窝才刚入门啊QAQ) (最水的一篇博客,不接受反驳) P3384 【模板】树链剖分 代码 #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<string> #include<cstring> #include<cstdlib> #include<queue> using namespace std; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } const int maxn=1e5+10; int n,m,r,mod; int w[maxn],wt[maxn]; int fa[maxn],son[maxn],size[maxn],dfn[maxn],dep[maxn],top[maxn],tim=0; int sum[maxn<<2],laz[maxn<<2]

浅谈树链剖分

|▌冷眼眸甩不掉的悲伤 提交于 2019-11-29 14:20:42
浅谈树链剖分 本篇随笔讲解图论中的树链剖分相关内容。 树链剖分是树上问题的极常用操作,可以说不会树链剖分,一半以上的树上难题都毫无思路。其重要性不言而喻。想要流畅阅读本篇博客并学习树链剖分,需要读者具有一定的图论基础,并对树形结构和深搜算法有基本的认识。由于本蒟蒻的水平可能不足支持强大的树剖的讲解,所以题解中的一些不足之处敬请大佬们指正。 树链剖分的基本概念 树链剖分,顾名思义,就是把树拆成链。根据树的形态,我们可以很容易的发现,任何一棵树都会有很多条链正好把树完全拆分。但是树链剖分并不是单单地把树拆成链。它拆出的链有 “轻重之分” 。 那么什么是轻重链呢? 这就涉及到了树链剖分的一些基本概念名词,如下述。 重儿子 :我们知道,除叶子节点之外,每个节点都会有若干个儿子节点,而只要这个节点不是叶子节点,它都是一棵子树的根。那么,这个父亲节点就有很多个儿子,而一定会有一个儿子的儿子最多,也就是子树最大。那么这个儿子节点就叫做 \(x\) 的重儿子。 轻儿子 :与重儿子对照理解,重儿子是唯一的,除了重儿子之外的所有儿子都是轻儿子。 重边 :父节点与重儿子组成的边(需要注意的是,这里的父节点不一定也是重儿子) 轻边 :除重边之外的边。 重链 :由重边连起来的链叫做重链,特别地,一条重链的顶部是一个轻儿子。 轻链 :由轻边连起来的链叫做轻链。 我们可以通过一张图来直观理解: