树形dp
青烟绕指柔!
我不怕千万人阻挡,只怕自己投降。
展开
-
[POI2017]Sabotaż
题目链接:[POI2017]Sabotaż有一个很显然的二分做法,二分之后dp,dp[x]为x的节点当中最多的叛徒个数。然后每次只能从子树当中选一个最大值转移。但是要快读卡常才能过。正解:dp[x] 为x节点未背叛的最小比例,然后考虑从儿子当中转移,有两种情况。当前儿子未背叛:dp[to],当前儿子背叛:算出儿子在所有儿子当中的size比例。显然选最小的转移即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include&原创 2020-11-19 20:01:50 · 249 阅读 · 0 评论 -
前缀单词
题目链接:前缀单词按照Trie建树,我们可以发现儿子和祖先关系是不能同时选取的。然后树形dp即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=60,M=N*N;int n,ch[M][26],ed[M],idx,dp[M]; char str[N];vec原创 2020-10-04 12:36:38 · 238 阅读 · 1 评论 -
规划
题目链接:规划这个式子显然可以01分数规划,然后问题就变成选n-m个点,并且是一个联通块的最大权值,树形dp即可。dp[i][j] 为以 i 为根节点,选取 j 个点的最大值。然后树上做背包即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=110;int原创 2020-10-04 11:28:04 · 86 阅读 · 0 评论 -
Codeforces - Serval and Rooted Tree
题目链接:Codeforces - Serval and Rooted Tree我们一定是控制最少的可以影响根节点的叶子,然后从大到小放数字。每次取max时,也就是子树中需要控制的最小的。取min的时候也就是求和。然后dp即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;con原创 2020-09-29 13:00:42 · 176 阅读 · 0 评论 -
道路摧毁
题目链接:道路摧毁dp[0/1]分别代表子树中两种点的最小代价。然后树形dp一下即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=2e5+10,M=N*2;int n,mx,my,a[N],dp[N][2];int head[N],nex[M],to[M]原创 2020-09-21 22:50:22 · 203 阅读 · 0 评论 -
Codeforces - Masha and Cactus
题目链接:Codeforces - Masha and Cactus考虑dp[x] 为x的子树中的最大值。考虑枚举LCA转移,我们可以发现转移是一条链,然后树剖维护链上子节点的和进行优化即可。考虑转移一条链的时候,我们需要加上这条链上相邻的节点的dp[v],我们可以对每个点维护一个子节点的sum - 当前节点的dp[x] 然后链上求和就是相邻节点的dp之和。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<原创 2020-09-08 23:57:39 · 719 阅读 · 0 评论 -
Codeforces - Ehab and a component choosing problem
题目链接:Codeforces - Ehab and a component choosing problem显然 Σa / k,相当于取平均值,我们得到最大值肯定是k=1的时候。求最大值树形dp即可。但是与此同时可能存在多个最大值。再次树形dp求出即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namesp原创 2020-08-24 10:21:04 · 172 阅读 · 0 评论 -
LUK-Triumphal arch
题目链接:LUK-Triumphal arch首先考虑二分最小的k。然后转为判定合法性。我们可以树形dp。dp[x] 为当前 B 在x点,然后A需要在子树中染色的最小点数。dp[x] = Σ dp[v]+1 - k最后判断dp[1]==0即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespac原创 2020-08-23 12:02:01 · 267 阅读 · 0 评论 -
Codeforces - Famil Door and Roads
题目链接:Codeforces - Famil Door and Roads我们根据 x = lca || y = lca ,或者其他情况来讨论。如果是前者,那么满足的环肯定是 lca 之上的一个点,和当前深度大的节点的子节点。如果是后者,那么肯定是两个节点的子节点。所以我们对每一部分单独求期望即可。某个节点之下的节点到当前节点的期望,我们可以用总距离除以点数计算。所以计算这个先dp,然后换根即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-al原创 2020-08-12 21:08:35 · 192 阅读 · 0 评论 -
Codeforces - Chloe and pleasant prizes
题目链接:Codeforces - Chloe and pleasant prizes两颗子树必然存在一个公共祖先,枚举公共祖先即可。然后从公共祖先的儿子中选最大的两个子树。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=2e5+10;int n,a[N],mx原创 2020-08-12 18:13:05 · 191 阅读 · 0 评论 -
HDU - 6540
题目链接:HDU - 6540树形dp,dp[x][i] 为距离节点 x 的最大关键节点距离为 i 的方案数。我们先算不选当前节点的方案数。对于儿子节点,直接组合即可。然后再考虑一个儿子单独和根组合。然后如果这个节点是关键节点,那么我们就让小于等于k的方案数 * 2 即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longu原创 2020-07-27 10:01:07 · 278 阅读 · 0 评论 -
HDU - 6769
题目链接:HDU - 6769考虑二分。然后dp[i][j]为当前到节点 i,选了 j 个权值A的边的到 i 节点能达到的最长的最短链长。然后初始化为INF,只要任意组合可以满足加起来小于mid,那么我们就可以更新当前节点的 dp 值。最后只需要看dp[1][k]的点是否被更新即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long原创 2020-07-24 23:02:47 · 327 阅读 · 0 评论 -
[HAOI2015]树上染色
题目链接:[HAOI2015]树上染色考虑子树当中所有边的贡献即可。然后就能简单做树上背包了。但是要注意枚举的顺序,应该从大到小更新,否则某个状态会多次被加。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=2e3+10,M=N<<1;int n,K,原创 2020-07-24 22:52:05 · 140 阅读 · 0 评论 -
买一送一
题目链接:买一送一因为我们只需要对每个点维护到根节点的一条链,所以可以想到用入栈添加出栈删除来维护到当前节点的一条链上信息。当前节点的答案可以由上一个节点转移,然后加上到之前一样颜色的点之间的不同颜色数量。然后注意选两个相同节点的情况。注意细节即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespa原创 2020-07-23 23:30:10 · 322 阅读 · 0 评论 -
Codeforces - Valid Sets
题目链接:Codeforces - Valid Sets枚举最大值作为根即可,然后能递归到的点一定是小于等于这个权值,并且之差小于等于d。但是显然当两个权值相等的时候就会多算,那么我们只算一边即可,相同权值,只往编号小的点递归。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const原创 2020-07-17 16:22:55 · 152 阅读 · 0 评论 -
Codeforces - Road Improvement
题目链接:Codeforces - Road Improvement有一个很显然的dp方程dp[x] = dp[v]+1的乘积和、但是换根的时候,可能会出现dp[x]%mod==0,然后用逆元就会错。所以我们需要处理前缀和后缀乘积。注意,计算之后再递归下去,不然递归下去会影响当前的前缀和后缀乘积。或者对每个点开和vectorAC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h&g原创 2020-07-17 15:25:40 · 166 阅读 · 0 评论 -
Codeforces - Work Group
题目链接:Codeforces - Work Group显然可以树dp,dp[x][0/1]为点x,包括点x一共选了奇数或者偶数个合法的最大值。最后对于当前点看是否选择。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=2e5+10;int n,a[N],dp[N原创 2020-07-16 17:41:20 · 223 阅读 · 0 评论 -
Codeforces - Alternating Tree
题目链接:Codeforces - Alternating Tree做法很显然,就是看每个点的贡献。然后就是看作为链上奇数位置,和偶数位置的贡献。这个我们直接看子树到外面,和外面到子树分别计算即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int mod=1e9+7;原创 2020-06-21 20:01:23 · 232 阅读 · 0 评论 -
点对最大值
题目链接:点对最大值显然可以树dp。dp[x]为从子树到点x的最大权值。然后我们每次对一个点记录,从子树来的最大值和次大值。每次转移即可,或者是直接到根。要注意初始值为-1e9而不是0AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e6+10,M=N&原创 2020-06-01 21:20:50 · 199 阅读 · 0 评论 -
旅游规划
题目链接:旅游规划显然我们可以先求出直径,然后枚举每一个点。要么是儿子之间组成最大长度,要么是最大的儿子加祖先过来的长度。树dp一遍,然后换根即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>using namespace std;const int N=2e5+10;int n,vis[N],mx1[N],mx2[N],mx[N],d;vector<i原创 2020-05-29 18:25:35 · 280 阅读 · 0 评论 -
[BOI2003]Gem 气垫车
题目链接:[BOI2003]Gem 气垫车显然总颜色数不会太多,随便设置个上线暴力dp即可。转移的时候可以前缀和优化一下。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e4+10;int n,dp[N][20],mi[20],res=1e9;vecto原创 2020-05-27 14:57:41 · 248 阅读 · 0 评论 -
赛道修建
题目链接:赛道修建显然可以树dp,然后换根,因为数据较大,所以需要bitset优化。但是bitset不具有可减性,因为某个位置可能是多个1,如果直接异或掉,就没了,就错了。所以我们换根的时候,用一个数组来表示从根到某个点的距离是否可行。然后每次转移的时候,需要从父亲节点的所有儿子转移过来,所以需要做一个前后缀bitset。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>原创 2020-05-19 23:22:18 · 273 阅读 · 0 评论 -
[SDOI2011]消耗战
题目链接:[SDOI2011]消耗战以前写虚树都没发现这么水的题。。。。显然总共节点不多,所以我们可以想到建立虚树。然后对于每个点,我们预处理出1号点到每个点的最小边权即可,然后就能dp了。因为每次都是从1号点开始,每次把1号点放进虚树即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace st原创 2020-05-16 18:07:06 · 215 阅读 · 0 评论 -
Interesting Vertices
题目链接:Interesting Vertices随便从某个点开始dfs,维护当前子树的颜色数。如果当前点合法:无颜色,所有子树都有颜色,子树中颜色数不为k,保证往上的子树也有颜色,根节点除外。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=2e5+10;i原创 2020-05-13 12:18:06 · 264 阅读 · 0 评论 -
城市环路
题目链接:城市环路显然如果是树就很简单了,现在变成了基环树,考虑断掉任意一条边即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e5+10;i...原创 2020-05-07 14:14:00 · 166 阅读 · 0 评论 -
部门聚会
题目链接:部门聚会随便dp一下就行,看当前是否出席会议。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e5+10;int n,rt,deg[N]...原创 2020-04-25 14:09:10 · 137 阅读 · 0 评论 -
树上的等差数列
题目链接:树上的等差数列显然如果直接存dp[x][d] ,表示到点x公差为d的最大长度。空间不够。但是其实需要用到的d很少,所以直接用map存即可。因为叶子节点不好更新,所以我们dp[x][d]实际长度为dp值加一即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h...原创 2020-04-24 21:51:55 · 238 阅读 · 0 评论 -
Justified Jungle
题目链接:Justified Jungle显然可以割点边数+1,一定是n的因子。然后枚举n的因子,比如当前 x+1是n的因子。那么割 x 条边,剩下 (x+1) 个连通块,且大小为 n/(x+1) ,所以我们树的子树size为 n/(x+1) 的个数一定要有x+1个。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#i...原创 2020-04-22 18:35:11 · 346 阅读 · 0 评论 -
路径
题目链接:路径直接点分或者树dp。树dp更简单。直接dp[x][0/1]表示当前x的子树中长度为奇数或者偶数的最长路径即可。每次更新奇偶最大值,次大值,然后更新答案即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long lon...原创 2020-04-15 11:36:25 · 172 阅读 · 0 评论 -
黑白树
题目链接:黑白树显然贪心从叶子往上染色一定是最优的。问题就是当前未被儿子覆盖的时候,我们可能选择染下面的点,使得影响的祖先更多。所以递推一下。dp[x]就是当前能影响的祖先个数。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int lon...原创 2020-04-07 17:02:47 · 239 阅读 · 0 评论 -
Codeforces - Ilya And The Tree
题目链接:Codeforces - Ilya And The Tree对于每个点其实只有删除或者不删除。所以从上往下做记忆化即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace st...原创 2020-04-04 20:50:02 · 154 阅读 · 0 评论 -
51NOD - 1677treecnt
题目链接:51NOD - 1677treecnt显然可以考虑每条边的贡献。假设这条边左边s个点,右边n-s个点。只有左右都有点,那么这条边就会贡献答案。然后容斥计算就是总方案减去全在左边或者全在右边。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define...原创 2020-04-02 14:07:56 · 162 阅读 · 0 评论 -
[USACO12FEB]Nearby Cows G
题目链接:[USACO12FEB]Nearby Cows G状态表示很简单 dp[i][j]到i的距离为j的权值和,然后就可以从子树中转移了,然后考虑子树之外的贡献,做一下换根即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int lon...原创 2020-03-29 10:54:03 · 198 阅读 · 0 评论 -
Codeforces - Mahmoud and a xor trip
题目链接:Codeforces - Mahmoud and a xor trip考虑对每个点以及他的子树算贡献。对当前点,按位看贡献,然后就相当于计算这个点子树的当中,经过点x,且长度为奇数的路径条数。直接dp即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>...原创 2020-03-25 14:47:28 · 186 阅读 · 0 评论 -
Codeforces - The Tag Game
题目链接:Codeforces - The Tag Game显然先手的操作只有两种。令1为根要么直接往下跑到最远处。要么在可能的情况下,先往上走,然后再往下跑。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing...原创 2020-03-20 11:15:26 · 139 阅读 · 0 评论 -
Codeforces - Choosing Capital for Treeland
题目链接:Codeforces - Choosing Capital for Treeland显然,如果确定首都之后,我们可以O(n)计算出这个点的答案。然后这个东西可以换根吗?显然是可以的。换根即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#def...原创 2020-03-18 16:27:15 · 168 阅读 · 0 评论 -
Codeforces - Maximum White Subtree
题目链接:Codeforces - Maximum White Subtree比较裸的换根的,dp[x]表示子树当中最大的值即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std...原创 2020-03-12 22:07:05 · 237 阅读 · 0 评论 -
火山哥周游世界
题目链接:火山哥周游世界显然对于一个起点,直接树dp就可以求出,现在询问多个点,那么我们就要考虑是否可以换根。每个点的答案其实就是走出去到所有点再走回来-到某个必须点的最大值。如果我们分别求出前面和后面两个东西,就很好做换根了。换根的过程中要注意,某一部分是否存在重要点。考虑某个点走出去的max,我们分为到子树的max和往上面走的max。分别维护每个点走到子树的最大值和次大值即可。并且...原创 2020-02-28 21:56:27 · 312 阅读 · 0 评论 -
Codeforces - Tree Painting
题目链接:Codeforces - Tree Painting最喜欢写换根了,推推式子就能AC。显然,知道第一个点,那么整个答案就已知了,所以明显可以换根。我们令dp[x]为当前x已经为黑点了,子树的贡献,res[x]为x是第一个黑点的答案。推一推怎么向子树转移就行了。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")...原创 2020-02-23 15:42:11 · 208 阅读 · 0 评论 -
Codeforces - Tree with Maximum Cost
题目链接:Codeforces - Tree with Maximum Cost显然可以换根。推一推式子即可。很多式子都没用到,QAQ,本来以为需要的,结果式子推完发现可以抵消。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long l...原创 2020-02-20 12:35:08 · 158 阅读 · 0 评论