题目传送门 题意 一棵$N$个节点的树,初始时所有的节点都是白色,第一次可以选择任意一个把它涂成黑色.接下来,只能把与黑色节点原来相连的白色节点涂成黑色(涂成黑色的点视为被删去,与其它节点不相连).每一次涂的分数为涂的这个白色节点所在的联通块里的白色节点的个数.要把这$N$个节点都涂成黑色,求能获得的最大分数.(人工翻译+手打qwq,若有误差请告诉我) 分析 没有什么太大思路的题先乱搞 然后我们发现 我们在最开始随便把这棵树的其中一个节点涂成黑色之后,这个树的涂法就唯一确定了.涂了之后这棵树就会…
题目链接: http://codeforces.com/contest/1187/problem/E 题意: 给出一颗树,找到一个根节点,使所有节点的子节点数之和最大 数据范围: $2 \le n \le 2 \cdot 10^5$ 分析: 最暴力的方法是枚举所有的根节点,计算他们子节点之和,复杂度是$O(n^2)$ 但是可以发现,$a$作为根节点和$b$作为根节点,只有$a,b$节点的子节点数有变化 根的子节点数肯定是$n$,与他交换的点节点数是$x$的话,那么根的子节点数就变成$n-x$,交…
乍一看题意比较麻烦,好像要删点求联通性,但其实是相当于求以某一个节点为根时,他的所有后代(儿子,儿子的儿子等等)的儿子的总和最大. 两边dfs即可,第一遍dfs随便找一个点为根,求出每个节点的儿子数siz[],第二遍dfs以每个点作为根更新ans. 这里注意:如果u为根,u是v的父亲,且此时u后代的和为siz[u] = val,那么v为根时后代和为val-siz[v]+n-siz[v],以此关系作为第二遍dfs的依据. #include <bits/stdc++.h> using namesp…
我--又诈尸了-- 代码几乎都不会写了,打场CF居然上分啦,开心!(虽然还是比不过列表里的各路神仙) 题目链接 题目描述 一棵\(n\)个点的有根树,规定一种dfs序(规则:编号小的点优先dfs),\(m\)次询问一个点\(u\)和一个区间\([l, r]\),求dfs序在这个区间内的叶子中,到\(u\)最小的距离. \(n, m \le 500000\) 题解 这题--很简单-- 题面一上来给个什么欧拉遍历定义--我吓得比赛中没看这题--(实际上码量对于代码几乎都不会敲的退役选手来说,不是非常…
传送门 •参考资料 [1]:CodeForces 825G Educational Round #25 G :建树选根大法+O1大法+iostream解绑了还是慢 •题意 给定一颗包含 n 个节点的树,开始树的所有节点都是白色的: 给出 q 次询问,询问分为1.2两种: 将节点 x 涂成黑色. 询问节点 x 到所有的黑点节点的简单路径中的标号最小的那个点(包括起点和黑点) 题目保证第一次询问是 1 类型的. •题解 如果我们随便选取某节点作为根节点,那么询问的时候,我们要找到节点 x 到所有黑色…
题目链接 Tree $dp[x][i]$表示以x为根的子树中x所属的连通快大小为i的时候 答案最大值 用$dp[x][j]$ * $dp[y][k]$ 来更新$dp[x][j + k]$. (听高手说这类题的套路其实都差不多) 因为这题输出数据会很大所以用Java…… QAQ import java.util.*; import java.io.*; import java.math.*; public class Main{ static final int maxn = 710; stati…
传送门:http://codeforces.com/contest/1092/problem/F F. Tree with Maximum Cost time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a tree consisting exactly of nn vertices. Tree is a…
大意: n节点树, 每个点有权值, 三种操作: 1,换根. 2, lca(u,v)的子树权值全部增加x. 3, 查询子树权值和. 先不考虑换根, 考虑子树x加v的贡献 (1)对fa[x]到根的树链贡献为sz[x]*v; (2)对x子树内的点y贡献为sz[y]*v; 步骤(1)可以用单点更新子树求和实现, 步骤(2)可以子树更新单点求和实现 然后就是换根板子题了. 感觉蠢得不行的题啊, 还是打了好久, 怎么能这么菜啊 #include <iostream> #include <algori…
题意: 给你一棵无根树,每个节点有个权值$a_i$,指定一个点u,定义$\displaystyle value = \sum^v a_i*dist(u,v)$,求value的最大值 n,ai<=2e5 思路: 其实就是找一个节点作为根满足上述最大的value 直接枚举是$O(n^2)$的,肯定不行,我们要用到换根法 换根适用于这种无根树找根,两个跟直接产生的结果又有联系,可以相互转换的情况 对于这一题,我们让sum[u] = 以u为根的子树的$\sum a_i$ 这样,从父亲节点u向儿子节点v转…
http://codeforces.com/contest/1187/problem/E 分析:问得分最高,实际上就是问以哪个节点出发得到的分数最多,而呈现成代码形式就变成了换根,max其得分!!!而要利用之前算过的得分来求. #include<bits/stdc++.h> using namespace std; typedef long long ll; ; vector<int>e[M]; int son[M]; ll ans; int n; void dfs(int u,i…
树链剖分 树链剖分是一种对树的分治, 可以把树上的任意一条链分解为 \(O(\log n)\) 条在dfs序上相邻的子链, 便于数据结构(如线段树)来维护. 另外, 子树在dfs序上也是一个连续的区间, 同样可以利用数据结构维护. Code //sgt: // chg(v,l,r,rt,rl,rr) 区间修改 // que(l,r,rt,rl,rr) 区间查询 //树剖 int sz[nsz],fa[nsz],son[nsz],dep[nsz];//got through dfs1 int df…
Description zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀. 问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树.这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的.遥远的国度的每个城市有一个防御值,有些时候RapiD会…
LINK:树论 不愧是我认识的出题人 出的题就是牛掰 == 他好像不认识我 考试的时候 只会写42 还有两个subtask写挂了 拿了37 确实两个subtask合起来只有5分的好成绩 父亲能转移到自己的子树内部的一点所以要从叶子结点往根考虑. 一个棋子的时候 单独某个点的SG函数不难推 这个点可以放到儿子任意一点 而儿子的SG函数值已知就很容易推出来了. 当然叶子结点的SG函数值为0. 显然整棵树的SG函数为异或和 可以看成若干个不交的游戏的组合. 考虑某个点两个棋子的时候的SG函数 经过不断…
Codeforces 题面传送门 & 洛谷题面传送门 换根 dp 好题. 为啥没人做/yiw 首先 \(n\) 为奇数时答案显然为 \(0\),证明显然.接下来我们着重探讨 \(n\) 是偶数的情况. 考虑一棵树存在完美匹配的等价证明:我们考察每一条边,如果删掉该条边后两个连通块的大小都是奇数,那么显然我们如果贪心地对两个连通块进行二分图完美匹配,如果还剩至少三个点没被匹配,那么显然原图不存在二分图完美匹配,否则我们肯定会剩下该连通块的根节点,也就是这条边的一个端点.换句话,如果原图存在二分图完…
Codeforces 题面传送门 & 洛谷题面传送门 一种换根 dp 的做法. 首先碰到这类题目,我们很明显不能真的把图 \(G\) 建出来,因此我们需要观察一下图 \(G\) 有哪些性质.很明显我们可以把它看作 \(T_1,T_2\) 上分别有一个标记,每次可以将 \(T_1,T_2\) 上的某个标记沿着某条边移动一步,问 \(k\) 步之后标记刚好回到原位的方案数是多少. 显然两棵树是独立的,因此可以分开来考虑,我们记 \(dp1_{i,j}\) 表示 \(T_1\) 中从 \(i\) 开始…
传送门:http://www.51nod.com/Challenge/Problem.html#!#problemId=1812 题解:头一次写换根树DP. 求两条不相交的直径乘积最大,所以可以这样考虑:把一条边割掉,然后分别求两棵子树内的最长链乘起来就行了.由于负负得正,所以要再求一次最短链,就是把边权全部取负求一下就行了.然后就能通过dfs维护子树i内的答案dn[i]和不含以i为根的子树的答案up[i],dn[i]很好维护,重点是维护up[i],共5种可能:(1)从父亲的up继承过来(2)前…
题意 给定一棵 \(n\) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值. \(n\leq 5\times 10^5\) . 分析 记断掉一条边之后两棵树的直径为 \(A,B\) ,最长直径为 \(A+B+1\) 最短为 \(\max\{A\ ,B\ ,\lceil \frac{A}{2}\rceil+\lceil \frac{B}{2} \rceil +1\}\) . 维护每个点不同子树的前3长链和向上的最长链.不同子树的前2长路径和向上子树的最长路径. 这样…
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 512 MB Description 描述 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀. 问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树.这个国度有一个首都,我们可以把这个首都看做整棵树的根,但…
P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达,但是通过一条高速公路需要收取一定的交通费用.小明对这个地区深入研究后,觉得这个地区的交通费用太贵.小明想彻底改造这个地区,但是由于上司给他的资源有限,因而小明现在只能对一条高速公路进行改造,改造的方式就是去掉一条高速公路,并且重新修建一条一样的高速公路(即交通费用一样),使得这个地区的两个城市…
题目链接  BZOJ3083 换根不能真正地换. 令当前的根为$cnt$,要查找的子树根为$x$ $1$.$x = cnt$,那么要查找的区域就是整棵树. $2$.$x$在以$cnt$为根的子树内,那么要查找的区域就是以$x$为根的子树. $3$.$x$在以$cnt$为根的子树外 (1)$x$不是$cnt$的祖先,那么要查找的区域就是以$x$为根的子树. (2)$x$是$cnt$的祖先,设$y$为$x$到$cnt$方向上的第一个点,那么要查找的区域就是整棵树减去以$y$为根的子树. #inclu…
题目:http://poj.org/problem?id=3585 二次扫描与换根法,一次dfs求出以某个节点为根的相关值,再dfs遍历一遍树,根据之前的值换根取最大值为答案. 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; ],ct,d[],f[],deg[],ans,t; ]; struct N{ int to,next,w; }edge[]; void…
3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 4859  Solved: 1372[Submit][Status][Discuss] Description 描述 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀. 问题是这样的:遥远的国度有n个城市,…
题目链接 题意:给你一棵无根树,每次你可以选择一个点从白点变成黑点(除第一个点外别的点都要和黑点相邻),变成黑点后可以获得一个权值(白点组成连通块的大小) 问怎么使权值最大 思路:首先,一但根确定了,整棵树的权值就只需要模拟即可,所以思路就转换为求哪一个点为根的权值最大. 这题需要用到一个二次扫描换根的思想,我们可以先从任意一个点去进行树形dp 并且得到从这个点开始去逐渐更新他的儿子节点 #include<cstdio> #include<cstring> #include<…
.... 有点懒: 需要先理解几个概念: 1. LCA 2. 线段树(熟练,要不代码能调一天) 3. 图论的基本知识(dfs序的性质) 这大概就好了: 定义: 1.重儿子:一个点所连点树size最大的,这个son被称为这个点的重儿子: 2.轻儿子:一个点所连点除重儿子以外的都是轻儿子: 3.重链:从一个轻儿子或根节点开始沿重儿子走所成的链: 步骤: 在代码里,结合代码更清晰...(其实是太懒了) 有重点需要注意的东西在code中有提到,仔细看.... #include<bits/stdc++.h…
题面 https://www.luogu.com.cn/problem/P5666 分析 对于一棵以i为根的树来说,它的重心必然在其size大于等于sumsize/2的子树中. 那么断掉一条边e(u,v)时,我们对于断掉边的u,v进行讨论,然后向他们的重儿子倍增直到满足其size≤sumsize/2. 具体实现时可能存在两个重心,所以要判断一下找到的点的重儿子和其父亲. 然后换根的时候维护一下size和father就行了. 代码 #include <iostream> #include <…
析:显然,若没有换根操作,则为树链剖分板子题,但是这道题我们考虑换根操作 考虑这样一个性质:在一棵树上,两点的距离路径是唯一的!! 也就是说,我们在修改路径上的点权时,不必考虑根在哪里,直接利用模板修改即可 麻烦的地方在于查询操作,我分了三种情况来讨论:(设 root 为当前的根,id 为当前要查询的编号) 1.若 deep[id]>=deep[root] ,则跟对他没有影响,直接查询即可 2.若 deep[id]<deep[root] ,刚开始我是求出两点的 LCA ,然后查询 (1,num…
正题 题目链接:https://www.luogu.com.cn/problem/P4323 题目大意 给出\(n\)个点的树和加上一个点之后的树(编号打乱). 求多出来的是哪个点(如果有多少个就输出编号最小的). \(1\leq n\leq 10^5\) 解题思路 定义一下\(hash\)值\(P(i)\) 我的做法是\(P(i)=p^i\),\(p\)是一个质数,当然这样好像容易被卡,安全点的做法是用第\(i\)个质数或者直接用复数\(hash\). 然后定义一下带根的\(hash\)值 \…
题面 题解 先解决第一个子问题吧,它才是难点 Subtask_1 我们可以先用一个简单的树形DP处理出每棵树内部的dis和,记为dp0[i], 然后再用一个换根的树形DP处理出每棵树内点 i 到树内每个点的距离和,记为dp[i], 好,现在分两个连通块跟三个连通块两种情况讨论 两个连通块 把两棵树A,B合并到一起,我们得先确定两个连接的点, 若其分别为 i,j,不难发现答案就是 dp0[A] + dp0[B] + dp[i] * size[B] + dp[j] * size[A] + size[…
传送门 换根dpdpdp傻逼题好像不好码啊. 考虑直接把每一个二进制位拆开处理. 先dfsdfsdfs出每个点到1的异或距离. 然后分类讨论一波: 如果一个点如果当前二进制位到根节点异或距离为1,那么对于当前二进制位到这个点距离为000的就是到根节点距离为111的,如果当前二进制位到这个点距离为111的就是到根节点距离为000的. 如果一个点如果当前二进制位到根节点异或距离为1,那么对于当前二进制位到这个点距离为000的就是到根节点距离为000的,如果当前二进制位到这个点距离为111的就是到根节…
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类对树的边进行轻重划分的操作,这样做的目的是为了减少某些链上的修改.查询等操作的复杂度. 目前总共有三类:重链剖分,实链剖分和并不常见的长链剖分 重链剖分 实际上我们经常讲的树剖,就是重链剖分的常用称呼. 对于每个点,选择最大的子树,将这条连边划分为重边,而连向其他子树的边划分为轻边. 若干重边连接在…