lca

1151 LCA in a Binary Tree (30 分)

久未见 提交于 2019-12-04 12:23:42
1151 LCA in a Binary Tree (30 分) The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U and V as descendants. Given any two nodes in a binary tree, you are supposed to find their LCA. Input Specification: Each input file contains one test case. For each case, the first line gives two positive integers: M ( ≤ 1,000), the number of pairs of nodes to be tested; and N ( ≤ 10,000), the number of keys in the binary tree, respectively. In each of the following two lines, N distinct integers are given as the inorder and preorder traversal sequences of the

noip 2015 天天爱跑步

不打扰是莪最后的温柔 提交于 2019-12-04 08:49:49
原文 LCA+桶+树上差分 1. 第一步 首先可以初步判断这个题肯定要计算 LCA ,方法有 倍增 / Tarjan-DFS ,我们就写个简单的倍增吧,使用 链式前向星 存储边。 选择1号结点开始dfs,别的结点也可以 dfs过程中计算 fa[][] 数组( fa[x][i] 表示 x x 结点的 2 i 2i 代祖先是谁)和deep[]数组( deep[x] 表示结点 x x 在树中的深度) #include<bits/stdc++.h> using namespace std; const int SIZE=300000; int n, m, tot, h[SIZE], deep[SIZE], fa[SIZE][20], w[SIZE]; //w[i]表示i结点出现观察员的时间 struct edge { int to, next; }E[SIZE*2], e1[SIZE*2], e2[SIZE*2]; //边集数组e1,e2留待备用 void add(int x, int y) //加边函数 { E[++tot].to=y; E[tot].next=h[x]; h[x]=tot; } void dfs1(int x) //dfs的过程中完成“建树”,预处理fa[][]数组, 计算deep[]数组 { for(int i=1; (1<<i)<=deep[x]; i++) fa

【题解】【BZOJ】4668 冷战

大城市里の小女人 提交于 2019-12-04 08:44:55
题外话: 你们知道想了半天思路提供给同学然后证明了半天时间复杂度然后考试结束的痛苦吗…… 看到连通性,我们会本能地想起并查集(想起LCT的说明您太强了orz) 题目要求输出的是 \((u,v)\) 这一点对最早在什么时候联通 考虑连边操作 显然,如果 \((u,v)\) 已经联通,那么连接它们两个是没有意义的 如果 \((u,v)\) 不连通,则必须连接它们两个 经过一番思考,我们思考出来以下思路: 若连接 \((u,v)\) ,则将 \(u\) 并查集合并到 \(v\) 并查集上 连出来的边设一个边权 \(val\) ,val为当前为第几个铁路 好像就没有了? 对于询问,我们直接往上一层层跳,跳出LCA,然后统计答案 在实际实现的时候,每个点会记录一个 \(v[i]\) ,表示i到fa[i]这条路径上的权值 同时,为了方便,我(在参考lzh的代码后)选取了另外一种更暴力的找LCA的方法 注意:不能路径压缩,为了保证时间复杂度我们使用按高度合并(学名不知道……) 期望?均摊?反正层数 \(O(logn)\) code: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=500010; const int inf

WOJ#3836 Sightseeing Trip

混江龙づ霸主 提交于 2019-12-04 08:40:05
描述   给定一张无向图,求图中一个至少包含 3 个点的环,环上的节点不重复,并且环上的边的长度之和最小。该问题称为无向图的最小环问题。在本题中,你需要输出最小环的方案,若最小环不唯一,输出任意一个均可。若无解,输出 No solution.。图的节点数不超过 100 。 输入 第一行两个正整数 n,m 表示点数和边数。 接下来 m 行,每行三个正整数 x,y,z ,表示节点 x,y 之间有一条长度为 z 的边。 输出 输出一个最小环的方案:按环上顺序输出最小环上的点。若最小环不唯一,输出任意一个均可。若无解,输出 No solution. 样例输入 5 7 1 4 1 1 3 300 3 1 10 1 2 16 2 3 100 2 5 15 5 3 20 样例输出 1 3 5 2 标签 CEOI1999 题解    其实这道题可以用Floyd。   容易知道,树加上一条非树边可以形成环。利用这个性质,我们可以先求出一棵最小生成树,然后通过枚举每一条非树边求出加上它之后所形成的环的大小并尝试更新答案。输出方案时直接在最小生成树上暴力跳就行了。时间复杂度O(mlogn)。   代码: #include<bits/stdc++.h> using namespace std; #define gc getchar template<typename T>void read(T&cn){

【模板】最近公共祖先(LCA)

女生的网名这么多〃 提交于 2019-12-04 08:19:24
题目 这,大概是我在CSP前最后的一篇模板题了吧。 时隔一年,昨天又一次成功地打对了LCA,可海星。 这里用的是倍增的写法。 Code: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> using namespace std; //Mystery_Sky // #define M 500001 #define INF 0x3f3f3f3f #define ll long long inline int read() { int x=0, f=1; char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } struct Edge{ int next, to; }edge[M<<1]; int n, m, cnt, t, s; int head[M], d[M], f[M][30]; queue <int> q; inline void add_edge(int u, int v) {edge[++cnt].to = v; edge[cnt].next

树结构

試著忘記壹切 提交于 2019-12-04 06:34:07
树 URAL1039 Anniversary Party \(O(n)\) 一棵树, 相邻点不能同时选, 问最大点权和 int ind[MAXN], val[MAXN]; int f[MAXN][2]; void DFS(int u, int fa) { f[u][1] += val[u]; for (int i = head[u]; i; i = adj[i].nex) { int v = adj[i].to; if (v == fa) continue; DFS(v, u); f[u][0] += max(f[v][0], f[v][1]); f[u][1] += f[v][0]; } } int main() { n = in(); for (int i = 1; i <= n; ++ i) val[i] = in(); for (int i = 1; i < n; ++ i) { int l = in(), k = in(); ++ ind[l]; addedge(k, l); } for (int i = 1; i <= n; ++ i) if (!ind[i]) { DFS(i, 0); printf("%d\n", max(f[i][0], f[i][1])); } return 0; } CF1038A.The Fair Nut and the Best Path

csp-s模拟89

♀尐吖头ヾ 提交于 2019-12-04 06:31:21
T1:   有个诡异的结论:最多按3次delete   然后类似于艾氏筛的dp就行了,复杂度 \(O(nloglogn)\) ,有点卡   正解是跑个最短路,感觉很优秀 T2:   考虑容斥,发现其实就是求:$\sum_{i=1}^{\lfloor \sqrt{n} \rfloor} \mu (i)* \lfloor n/(i^2) \rfloor $   其中 \(\lfloor n/(i^2) \rfloor\) 可以整除分块,那么复杂度瓶颈在于求莫比乌斯函数的前缀和   低于线性的求积性函数前缀和, 杜教筛 即可 T3:   Treap = Tree+Heap (x)   椎 = 树 + 堆 ( \(\surd\) )   呵,在理   考虑肯定不能模拟treap,因为weight值并不随机,所以并不平衡   考虑将离线下来,对key值排序,那么 \(k_u\) 和 \(k_v\) 的lca一定是它们区间中weight最大的点   然后就考虑如何求x到lca的距离,考虑treap中weight的性质可知距离即为从x到lca中weight单调递增的点的个数   说白了就是维护单调栈的大小,线段树维护单调栈即可 来源: https://www.cnblogs.com/Gkeng/p/11837314.html

关于树上的简单操作(暂时)

戏子无情 提交于 2019-12-04 06:10:27
倍增求LCA 1 #include<cstdio> 2 #include<iostream> 3 #define re register 4 #define in inline 5 #define N 500010 6 #define M 500010 7 using namespace std; 8 in int read(){ 9 int x=0,f=1; char c=getchar(); 10 while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*f; 13 } 14 struct node{ 15 int next,to; 16 }edge[M<<1]; 17 int n,q,s,cnt; 18 int head[M<<1],f[25][N],dep[N]; 19 20 in void add(int x,int y){ 21 edge[++cnt].next=head[x]; 22 edge[cnt].to=y; 23 head[x]=cnt; 24 } 25 26 void dfs(int u,int deep){ 27 dep[u]=deep; 28 for(re int i=head[u]

P1600 天天爱跑步

瘦欲@ 提交于 2019-12-04 05:28:45
P1600 天天爱跑步 这道题很久之前就想做了,但是还是拖到了现在; 看这道题的时候还是很懵,看了题解(话说这题解写的贼好)恍然大悟; 路径条数太多,一个个遍历会T,我们需要换一个思路,遍历观察员,这样就是O(n)的; 我们可以想,哪些点能对当前观察员做出贡献; 观察员在p点的w[p]时间观察,有一个等式dep[p]+w[p]=dep[s[i]],s[i]是一个起点, 满足这个等式的路径就会对观察点做出贡献; 然而这只是上行路; 如果p在一条路径的下行路,设dis[i]=dep[s[i]]+dep[t[i]]-2*dep[lca],那么dis[i]-w[p]=dep[t[i]]-dep[p]; 那么满足dis[i]-dep[p]=w[p]-dep[t[i]]的会对答案做出贡献; 我们设两个桶,分别装着上行路的贡献和下行路的贡献; 遍历到当前点时,就可以直接根据等式得出自己的答案; 由于lca的位置比较特殊,上行路下行路会算两遍,所以提前预处理减掉多余的部分; 我们可以知道,面对当前节点什么节点会对自己做出贡献,就是起点或终点在自己的子树上; 所以一旦离开了自己的子树,我们需要把已经没有用的路径做出的贡献从桶中减去,(毕竟桶里的是标量数值,并没有什么状态); p在上行路上的贡献不能减去,因为这条路径还能往上做出贡献,在下行路也是如此; 只有当前节点是这条路径的lca时

【学习笔记】OI模板整理

两盒软妹~` 提交于 2019-12-04 04:54:40
CSP2019前夕整理一下模板,顺便供之后使用 1. 数据结构 1.1. 虚树 描述: 给定树上的 \(k\) 个关键点,构建出一棵虚树,只有关键点和任意两个关键点的LCA会被保留,且原树上的祖先关系和虚树上祖先关系保持一致。可以证明虚树最多有 \((2k-1)\) 个点。 把所有关键点按DFS序排序,用一个栈维护动态加点连边即可。时间复杂度 \(O(k\log n)\) . 注意事项: 一定要处理好最先加入栈中的点(所有点的LCA). 代码: addedge0_(u,v) 表示在 \(u\) 和 \(v\) 之间连边,边权根据实际情况确定。 bool cmp(int x,int y) {return dfn[x]<dfn[y];} void build() { sort(ky+1,ky+kyn+1,cmp); rt = ky[1]; for(int i=2; i<=kyn; i++) rt = LCA(rt,ky[i]).first; tp = 1; stk[tp] = rt; n0++; kid[n0] = rt; isky[ky[1]] = true; for(int i=(rt==ky[1]?2:1); i<=kyn; i++) { int u = ky[i],lca = LCA(stk[tp],u).first; if(lca==stk[tp]) {tp++; stk