lca

9.18

倖福魔咒の 提交于 2019-11-30 18:21:58
图 > 1.无向图度数之和为偶数,且入度之和==出度之和 2.欧拉图:有且只有两个奇点(图是连通的) 3.欧拉回路:有0个奇点(图是连通的) 计算机语言 1.分为机器语言,汇编语言(不广泛使用的原因是编写难度大,而不是效率不高),高级语言(分为编译性语言和解释性语言)。 2.C 不是一种面向对象的高级计算机语言 循环队列 head(front) 指向队头元素的前一个空位置 tail(rear) 指向队尾元素 n是队列空间(下标范围:1~n) 整个循环队列的元素总个数为 (tail-head+n)%n # P3884 完全二叉树的子叶节点个数问题 完全二叉树的结点个数为4* n+3,求其叶结点个数 问题转化: 即最后一个叶结点的编号为 4*n+3 , 那么它的父亲节点编号为 floor((4*n+3)/2)=2*n+1 , 因此叶结点个数总共有 (4* n+3)-(2*n+1)=2*n+2 ; [JLOI2009]二叉树问题 树剖板子题,不过因为读错题交了n发,题上说的是到根节点的距离……但其实数据求的是到lca的距离……,不过还有80pts,不错了。 思路: Subtask1: 深度和宽度可以在dfs1的时候顺带处理(lca倍增没办法) Subtask2: “距离”就是(deep[qu]-deep(lca))* 2+deep[qv]-deep(lca) P2420 让我们异或吧

2019清北学堂学习笔记

…衆ロ難τιáo~ 提交于 2019-11-30 17:43:33
暴力求解法 迭代加深搜 适用于搜索树深度不确定的时候,可以使用迭代加深搜。 步骤: 1.枚举maxd表示最深枚举深度; 2.假设当前深度为g(n),乐观估计至少要h(n)层才能到达叶子节点,那么g(n)+h(n)>maxd时,就应该剪枝。 在我理解看来,乐观估计的意思是说不去管所有的限制,然后去计算当前点到终点的距离或者所需要的操作数量,即还需要h(n)层,这时候的h(n)才是最好的,即最小(大)的,可以利用来剪枝。A*就是把状态乐观估计还要h(n)层才到达的想法使用到bfs上面。 双向搜索 对普通搜索的改进,使用的是BFS,大体流程就是从起点开始向终点搜,终点开始向起点搜,然后就直到第一个搜索碰到第二个或者是第二个碰到了第一个,然后答案就是两个搜索步数的和再减去1。比较典型的例题有魔板,然而那个题目一共3个变换方式,还可以不用双向搜索。 分治算法 数列上的分治 顾名思义,数列上的分治就是日常用的分治,最经典的例题就是求逆序对数量。使用的算法是归并排序,比较两个指针所对应的数字,如果左边的大于右边的,那么就说明,当前左边的指针到mid的所有数字都是大于右边指针所指的数字,那么答案就应该加上mid-l+1。 CDQ分治 可以代替数据结构的利器,可以解决的问题是区间加和单点修改。 \(\color{red}{流程:}\) 1. 按所有的按所有的操作等分分成前后两部分 2.

打 板 子

北战南征 提交于 2019-11-30 16:29:05
记录打板子的速度...(争取每周都打一轮) 数据结构:   并查集   Trie   可持久化Trie   树状数组   线段树   树链剖分   Splay   动态树   主席树   树套树   分块   点分治   cdq分治   整体二分   莫队   带修莫队   树上莫队   树上带修莫队 数学   线性筛   数论分块   gcd   exgcd   线性求逆元 欧拉定理   中国剩余定理   ex中国剩余定理   卢卡斯定理   莫比乌斯函数   0/1分数规划     欧拉函数   矩阵乘法   高斯消元   BSGS   FFT   NTT   杜教筛 图论: kruskal prim   tarjan-LCA   倍增LCA   基环树   点双   边双   缩点   网络流   费用流 来源: https://www.cnblogs.com/Hikigaya/p/11604269.html

树上增倍求解LCA 模板(未写完)

和自甴很熟 提交于 2019-11-30 15:14:01
//详解见 https://www.cnblogs.com/zwfymqz/p/7795299.html //博主: 自为风月马前卒 https://www.cnblogs.com/zwfymqz/ // 洛谷 P3379 最近公共祖先 链接 https://www.luogu.org/problem/P3379 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int MAXN = 1e5+10; 7 8 struct node { 9 int v, next; 10 } edge[MAXN]; 11 12 int head[MAXN]; 13 int num = 1; 14 inline void add_edge(int x, int y) { 15 edge[num].v = y; 16 edge[num].next = head[x]; 17 head[x] = num++; 18 } 19 20 int f[MAXN][21]; 21 int deep[MAXN]; 22 int n, m, root; 23 void dfs(int cur) { 24 for(int i = head[cur]; i != -1; i = edge

gym102201F_Fruit Tree

风流意气都作罢 提交于 2019-11-30 14:56:22
题意 给一棵带权树,多次询问路径上出现次数超过一半的数。 分析 dfs序建主席树,维护的就是根到某个节点这段路径的值域情况。 因为题目所求的不是一般的众数,而是出现次数大于一半的,所以在主席树上可以直接二分,看两个子树的值域哪个大于一半,就走哪个子树,如果都为一半,返回-1。 树上主席树的查询不同于序列上的主席树,不是子树做差,而是子树相加减去两倍LCA对应的树,然后这样减去之后会把LCA对应的点也给减去,所以要根据LCA点权判断再加上。 有一道类似的题目,UVALive7831。 比赛时一直莫队莫队,最后还是莫不出来,太容易思想江化了。 代码 #include <bits/stdc++.h> using namespace std; const int N=1e6+50; struct Edge{ int v,next; }e[N*2]; int cnt,head[N],a[N]; int n,qs,u,v; int fa[N][30],d[N],pw[30]; void init(){ cnt=0; memset(head,-1,sizeof(head)); pw[0]=1; for(int i=1;i<=20;i++){ pw[i]=pw[i-1]*2; } } void add(int u,int v){ e[cnt]=Edge{v,head[u]}; head[u]

HZOJ Tree

痴心易碎 提交于 2019-11-30 14:36:09
看到换根果断lct啊,然而其实我板子还没有打熟,还不会维护子树信息,于是就挂掉了…… 然而正解并不是lct。 其实好像很久很久以前将lca的时候好像讲到过一道换根的题,当时没有听懂。 直接说正解吧: 把dfs序搞出来用线段树维护。 用一个变量记录当前根节点,操作一直接改就行了。 然后是操作三: 分情况讨论,设当前根节点为root,询问的点为a。 如果root不在a的子树内,那么root不会影响a的子树,仍然输出1为根时的子树和就行了。 如果在子树内, 如图,如果要查询1的子树和,那么找到1与root这条链上靠近1的点,整体的和减去这个点的子树和就是了。(感性理解一下。) 那么这个点怎么求呢?只需要对于每个点把与他直接相连的儿子的dfs序塞到一个vector里,upper_bound然后-1就可以了。 操作二: 首先求出以1为根是a,b两点的lca。 与操作三类似,如果root不在lca的子树内,那么root不会影响lca,直接加就行。 如果在子树内,那么找a,b与root的lca中深度较大的那个。 之后就和操作三一样了。 来源: https://www.cnblogs.com/Al-Ca/p/11597858.html

CF629E Famil Door and Roads【树上计数+分类讨论】

不打扰是莪最后的温柔 提交于 2019-11-30 13:00:19
Online Judge : Codeforces629E , Luogu-CF629E Label :树上计数,分类讨论,换根 题目描述 给出一棵n个节点的树。有m个询问,每一个询问包含两个数a、b,我们可以对任意两个不相连的点连一条无向边,并且使得加上这条边后a,b处在一个环内。对于每一个询问,求这样的环的期望长度。 \(2<=n,m<=10^5\) 输入 第一行包括两个整数n,m,分别表示节点数和询问数。 接下来n-1行,每行两个整数u、v表示有一条从u到v的边。 接下来m行,每行两个整数a、b(a≠b),表示一个询问。 输出 对于每一个询问,输出满足条件的环的期望长度。答案保留6位小数。 样例 Input#1 4 3 2 4 4 1 3 2 3 1 2 3 4 1 Output#1 4.00000000 3.00000000 3.00000000 Input#2 3 3 1 2 1 3 1 2 1 3 2 3 Output#2 2.50000000 2.50000000 3.00000000 题解 题目求的是期望,其实就是求两个东西, \(all=\) 能形成环的个数, \(ans=\) 所有环的长度总和,两者相除得到答案。 转化为树上的计数问题。接下来分两种情况讨论。 先交代下面会用到的数组,及其意义。 \(sz[x]\) :以x为根的子树所含节点的个数。 \(dep[x

树链剖分

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

[CSP-S模拟测试]:attack(支配树+LCA+bitset)

依然范特西╮ 提交于 2019-11-30 12:25:25
题目传送门(内部题55) 输入格式 第一行,包含两个整数:$n,m,q$,表示敌军城市数、路数和情报数。 接下来$m$行,每行包含两个整数:$u,v$,表示从$u$到$v$包含一条单向道路。 接下来$q$行,每行包含一些整数:$k\ u_1\ u_2...u_k$,表示敌军会向$u_1...u_k$这$k$个城市派遣大军。 输出格式 对于每个询问,输出一行包含一个整数表示必经的城市数。 样例 样例输入1: 4 3 2 1 2 2 3 2 4 2 3 4 2 2 4 样例输出1: 2 2 样例输入2: 4 4 1 1 2 1 3 2 4 3 4 1 4 样例输出2: 2 数据范围与提示 样例$1$解释: 两个询问的必经点为:$1,2$ 样例$2$解释: 询问的必经点为:$1,4$ 数据范围: 对于$10\%$的数据,$1\leqslant n\leqslant 7,1\leqslant m\leqslant 10,1\leqslant q\leqslant 100$; 对于$40\%$的数据,$1\leqslant n\leqslant 50,000,m=n-1,1\leqslant q\leqslant 100,000$; 对于$100\%$的数据,$1\leqslant n\leqslant 50,000,1\leqslant m\leqslant 100,000,1

乱搞 - LCT求LCA

浪尽此生 提交于 2019-11-30 12:15:57
神犇学弟说LCA要用LCT求,于是我就听他的话写了一个LCT~ Code: #include <bits/stdc++.h> #define N 500005 #define lson t[x].ch[0] #define rson t[x].ch[1] #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout) using namespace std; int edges; int sta[N],hd[N<<1],nex[N<<1],to[N<<1],dep[N]; void add(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } struct Node { int ch[2],f,val,rev; }t[N]; int isrt(int x) { return !(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x); } int get(int x) { return t[t[x].f].ch[1]==x; } void mark(int x,int d) { if(!x) return; t[x].val=d; } void markrev(int x) { if(!x) return; t