题意

题目链接

分析

  • 首先解决 \(subtask3\) ,我们的策略就是进入子树,然后用其它子树来抵消,注意在子树内还可以抵消。

  • 可以转化为此模型:有一个数列 \(a\) ,每次我们可以选定两个值 \(>0\) 的数并让他们同时减 1,让最后 \(S=\sum a\) 最小。

    • 如果最大的数 \(a_{mx}\ge \frac{S}{2}\) ,显然答案为 \(2*a_{mx}-S\) 。

    • 否则我们每次把最大和次大的两个数进行操作,容易证明最后的答案为 \(S\ \rm mod\ 2\) 。

  • 现在数列的每一项就是子树的大小。

  • 也就是说,如果我们能够尽量多地让重儿子内部相互抵消(假设最多抵消 \(x\) 个节点,那么可以保留的节点就是 (\(x+2k+1\))),以至于重儿子剩余的大小 \(\le \frac{S}{2}\) 且保持最大或最大-1(如果只有两棵子树,且初始次大子树比最大子树小1不会影响讨论),就可以让结果变得至多为 1 了。

  • 发现这变成了一个子问题,所以记状态 \(f_u\) 表示在 \(u\) 进行一系列抵消后最少剩下多少节点。转移就比较显然了。

  • 对于不止查询一号点的情况,给每个点记个最大和次大的儿子, dfs 到 \(u\) 时把路径上的点看成一个点即可。

  • 时间复杂度 \(O(n)​\) 。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define go(u) for(int i = head[u], v = e[i].to; i; i=e[i].lst, v=e[i].to)
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define pb push_back
#define re(x) memset(x, 0, sizeof x)
inline int gi() {
int x = 0,f = 1;
char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) { x = (x << 3) + (x << 1) + ch - 48; ch = getchar();}
return x * f;
}
template <typename T> inline bool Max(T &a, T b){return a < b ? a = b, 1 : 0;}
template <typename T> inline bool Min(T &a, T b){return a > b ? a = b, 1 : 0;}
const int N = 1e5 + 7, inf = 0x3f3f3f3f;
int n, W, T;
int ans[N], dep[N];
vector<int>G[N];
struct data {
int son, f;
data(){}data(int son, int f):son(son), f(f){}
bool operator <(const data &rhs) const {
if(son != rhs.son) return son < rhs.son;
return f > rhs.f;
}
bool operator ==(const data &rhs) const {
return son == rhs.son && f == rhs.f;
}
}f[N][2], g[N];
void Add(int a, int b) {
G[a].pb(b);
G[b].pb(a);
}
void dfs1(int u, int fa) {
g[u].son = 1;
for(auto v:G[u]) if(v ^ fa) {
dep[v] = dep[u] + 1;
dfs1(v, u);
if(f[u][0] < g[v]) {
f[u][1] = f[u][0];
f[u][0] = g[v];
}else if(f[u][1] < g[v]) {
f[u][1] = g[v];
}
g[u].son += g[v].son;
}
if(f[u][0].son) {
if(g[u].son - f[u][0].son - 1 >= f[u][0].f + 1)
g[u].f = (g[u].son - 1) % 2;
else
g[u].f = f[u][0].f + 1 - (g[u].son - f[u][0].son - 1);
}else g[u].f = 0;
}
void dfs2(int u, int fa, data mx) {
data now = max(mx, f[u][0]);
int son = n - dep[u];
if(now.son) {
if(son - now.son - 1 >= now.f + 1)
ans[u] = (son - 1) % 2;
else
ans[u] = now.f + 1 - (son - now.son - 1);
}
for(auto v:G[u]) if(v ^ fa) {
if(f[u][0] == g[v]) dfs2(v, u, max(mx, f[u][1]));
else dfs2(v, u, max(mx, f[u][0]));
}
}
int main() {
W = gi(), T = gi();
while(T--) {
n = gi();
rep(i, 1, n) G[i].clear(), f[i][0] = f[i][1] = g[i] = data(0, inf);
rep(i, 1, n - 1) {
int a = gi(), b = gi();
Add(a, b);
}
dfs1(1, 0);
dfs2(1, 0, data(0, inf));
if(W == 3)
printf("%d\n", ans[1] == 0);
else
rep(i, 1, n) printf("%d", ans[i] == 0);
puts("");
}
return 0;
}

[清华集训2017]榕树之心[树dp]的更多相关文章

  1. [LOJ#2330]「清华集训 2017」榕树之心

    [LOJ#2330]「清华集训 2017」榕树之心 试题描述 深秋.冷风吹散了最后一丝夏日的暑气,也吹落了榕树脚下灌木丛的叶子.相识数年的Evan和Lyra再次回到了小时候见面的茂盛榕树之下.小溪依旧 ...

  2. 【题解】P4247 [清华集训]序列操作(线段树修改DP)

    [题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...

  3. [LOJ#2324]「清华集训 2017」小Y和二叉树

    [LOJ#2324]「清华集训 2017」小Y和二叉树 试题描述 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙 ...

  4. Loj #2331. 「清华集训 2017」某位歌姬的故事

    Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ...

  5. Loj 2320.「清华集训 2017」生成树计数

    Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...

  6. 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)

    [UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ...

  7. loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主

    #2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较   题目描述 "A fight? Co ...

  8. [LOJ#2326]「清华集训 2017」简单数据结构

    [LOJ#2326]「清华集训 2017」简单数据结构 试题描述 参加完IOI2018之后就是姚班面试.而你,由于讨厌物理.并且想成为乔布斯一样的创业家,被成功踢回贵系. 转眼,时间的指针被指向201 ...

  9. [LOJ#2323]「清华集训 2017」小Y和地铁

    [LOJ#2323]「清华集训 2017」小Y和地铁 试题描述 小Y是一个爱好旅行的OIer.一天,她来到了一个新的城市.由于不熟悉那里的交通系统,她选择了坐地铁. 她发现每条地铁线路可以看成平面上的 ...

随机推荐

  1. [PC]两个蓝牙耳机同时输出相同音源

    需求:和老婆一起玩双人同屏游戏(以撒的结合:抗生),但需要带上蓝牙耳机玩. 设备:2个蓝牙耳机.1个蓝牙接收器.1台Win10系统电脑. 通过关键字搜索出一个解决方案(Output audio to ...

  2. 【hexo】03config文件配置详解

    YAML 是专门用来写配置文件的语言,非常简洁和强大,我们的配置文件就是这种格式.需要了解的只有: # 我是文配置件的注释 重要提示,例如:"theme: landspace"中冒 ...

  3. python基础 - 字符串作

    split(sep=None, maxsplip=-1) 从左到右 sep 指定分隔字符串,缺省情况下空白字符串,指定的字符串会被切掉 maxsplit 指定分隔次数,-1 表示遍历 rsplit(s ...

  4. IDEA设置注释的颜色

    IDEA默认的灰色注释确实让人看不清,但如果把灰色调成黑色又和代码的颜色相同了,所以,不如给注释添加上绿色的背景,又护眼又容易分辨 新版本的IDEA打开Settings——Editot——Color ...

  5. 【JavaScript】获取当前页的URL与window.location.href

    原文:http://blog.csdn.net/yongh701/article/details/45688743 版权声明:本文为博主原创文章,未经博主允许欢迎乱转载,标好作者就可以了!感谢欣赏!觉 ...

  6. SA-题目

    SA的题目 差异:https://lydsy.com/JudgeOnline/problem.php?id=3238 题意概述:给定一个长度为 $n$ 的字符串 $S$,令 $T_ i$ 表示它从第 ...

  7. [笔记]后缀数组SA

    参考资料这次是真抄的: 1.后缀数组详解 2.后缀数组-学习笔记 3.后缀数组--处理字符串的有力工具 定义 \(SA\)排名为\(i\)的后缀的位置 \(rk\)位置为\(i\)的后缀的排名 \(t ...

  8. 判断MS SQLSERVER临时表是否存在

    drop table  #tempcitys select * into #tempcitys from hy_citys 上面的语句第一次运行的时候就肯定出错了,但第二次就不会.因为select * ...

  9. docker in docker 出现 libltdl.so.7 问题

    # docker ps -adocker: error while loading shared libraries: libltdl.so.7: cannot open shared object ...

  10. go标准库的学习-net

    参考:https://studygolang.com/pkgdoc 导入方式: import "net" net包提供了可移植的网络I/O接口,包括TCP/IP.UDP.域名解析和 ...