题意

题目链接

分析

  • 首先解决 \(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. linux上文件内容去重的问题uniq/awk

    1.uniq:只会对相邻的行进行判断是否重复,不能全文本进行搜索是否重复,所以往往跟sort结合使用. 例子1: [root@aaa01 ~]# cat a.txt 12 34 56 12 [root ...

  2. sql语句进阶教程

    转载自:http://blog.csdn.net/u011001084/article/details/51318434 最近从图书馆借了本介绍SQL的书,打算复习一下基本语法,记录一下笔记,整理一下 ...

  3. mysqlreport工具

    进行MySQL的配置优化,首先必须找出MySQL的性能瓶颈所在:而SHOW STATUS输出的报告正是用来计算性能瓶颈的参考数据.mysqlreport不像SHOW STATUS那样简单的罗列数据,而 ...

  4. Android中SELinux的TE简介【转】

    转自:https://blog.csdn.net/murphykwu/article/details/52457667 selinux的概念如上一篇链接所示: http://www.cnblogs.c ...

  5. 百度-淘宝-360搜索引擎搜索API

    百度(baidu) Api地址:http://suggestion.baidu.com/su?wd=设计&p=3&cb=window.bdsug.sug window.bdsug.su ...

  6. 英语初级学习系列-00-Name-介绍自己

    1. 询问名字 常用句子 1. Hi, may I have your name, please? 2. Could you please tell me your name? 3. Will it ...

  7. ABAP 内表访问表达式的性能

    内表访问表达式是ABAP 7.4中引入的重要特性,可以使语句变得更加简洁.美观.那么它的读写性能怎么样呢?我进行了一点点测试. 读取 测试代码,使用三种方式读取同一内表,分别是read table关键 ...

  8. select for update引发死锁分析

    本文针对MySQL InnoDB中在Repeatable Read的隔离级别下使用select for update可能引发的死锁问题进行分析. 1. 业务案例 业务中需要对各种类型的实体进行编号,例 ...

  9. c++11の多线程应用

    std::thread 应用十分方便,通过#include<thread>引入 std::thread t(subFunction); t.join(); 主线程将等待子线程完成后,继续调 ...

  10. Visual studio 2010 OpenGL配置

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/niuxiunan/article/details/24557935 题记:今天同学问我关于OpenG ...