首页 > 其他分享 >CF1039D You Are Given a Tree

CF1039D You Are Given a Tree

时间:2023-01-16 17:44:06浏览次数:79  
标签:paths Given int Tree 样例 tree CF1039D read fm

You Are Given a Tree

Luogu CF1039D

Codeforces CF1039D

题面翻译

有一棵 \(n\) 个节点的树。

其中一个简单路径的集合被称为 \(k\) 合法当且仅当:

树的每个节点至多属于其中一条路径,且每条路径恰好包含 \(k\) 个点。

对于 \(k\in [1,n]\),求出 \(k\) 合法路径集合的最多路径数
即:设 \(k\) 合法路径集合为 \(S\),求最大的 \(|S|\)。

\(n \leq 10^5\)。

题目描述

A tree is an undirected graph with exactly one simple path between each pair of vertices. We call a set of simple paths $ k $ -valid if each vertex of the tree belongs to no more than one of these paths (including endpoints) and each path consists of exactly $ k $ vertices.

You are given a tree with $ n $ vertices. For each $ k $ from $ 1 $ to $ n $ inclusive find what is the maximum possible size of a $ k $ -valid set of simple paths.

输入格式

The first line of the input contains a single integer $ n $ ( $ 2 \le n \le 100,000 $ ) — the number of vertices in the tree.

Then following $ n - 1 $ lines describe the tree, each of them contains two integers $ v $ , $ u $ ( $ 1 \le v, u \le n $ ) — endpoints of the corresponding edge.

It is guaranteed, that the given graph is a tree.

输出格式

Output $ n $ numbers, the $ i $ -th of which is the maximum possible number of paths in an $ i $ -valid set of paths.

样例 #1

样例输入 #1

7
1 2
2 3
3 4
4 5
5 6
6 7

样例输出 #1

7
3
2
1
1
1
1

样例 #2

样例输入 #2

6
1 2
2 3
2 4
1 5
5 6

样例输出 #2

6
2
2
1
1
0

提示

One way to achieve the optimal number of paths for the second sample is illustrated in the following picture:

Solution

学习根号分治的好题。

首先可以知道的是,确定 \(k\) 过后,答案最多是 \(\dfrac{n}{k}\),根据整除分块的思想可以得知这个答案的值只会有 \(\mathcal O(\sqrt n)\) 种取值方法。并且随着 \(k\) 的增大答案在不停减小。

根据这些,可以得知最后的结果应该是类似于整除分块一样的形式,递减并且相等的答案一定是连续的。

会发现,这个答案序列的前半部分的变化幅度很大,后半部分的变化幅度很小,因此可以设置一个阈值 \(siz\),小于等于 \(siz\) 的部分暴力做,大于的部分暴力做完二分找到答案连续段的右端点。这道题就完成了大半了。

考虑已知 \(k\) 如何计算答案。可以从下往上贪心,如果当前链的长度已经大于等于了 \(k\),那么就将答案加一。具体写法可以参考代码进行理解。

// Problem: You Are Given a Tree
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF1039D
// Memory Limit: 500 MB
// Time Limit: 7000 ms
// Author: Hanx16QwQ

#include<bits/stdc++.h>

using namespace std;

namespace Hanx16qwq {
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf;

template<class T> inline void read(T &x) {
    x = 0; T flag = 1; char b = getchar();

    while (!isdigit(b)) {flag = b == '-' ? -1 : 1; b = getchar();}

    while (isdigit(b)) {x = x * 10 + b - 48; b = getchar();}

    x *= flag;
}

template<class T, typename... Args> inline void read(T &x, Args&... args) {
    read(x), read(args...);
}

template<class T> inline void write(T x) {
    if (x < 0) putchar('-'), x = -x;

    if (x > 9) write(x / 10);

    putchar(x % 10 + '0');
}

template<class T> inline void writewith(T x, char c) {
    write(x), putchar(c);
}

const int _SIZE = 1e5;
int n;

struct EDGE {
	int nxt, to;
}edge[(_SIZE << 1) + 5];

int tot, head[_SIZE + 5];

void AddEdge(int x, int y) {
	edge[++tot] = {head[x], y};
	head[x] = tot;
}

int dfn[_SIZE + 5], fa[_SIZE + 5], cnt;
int order[_SIZE + 5];

void Dfs(int x, int F) {
	dfn[x] = ++cnt, order[cnt] = x, fa[x] = F;
	
	for (int i = head[x]; i; i = edge[i].nxt) {
		int twd = edge[i].to;
		
		if (twd == F) continue;
		
		Dfs(twd, x);
	}
}

int fm[_SIZE + 5], fs[_SIZE + 5];

int Solve(int k) {
	memset(fm, 0, sizeof fm);
	memset(fs, 0, sizeof fs);
	int res = 0;
	
	for (int i = n; i; --i) {
		int x = order[i], y = fa[x];
		
		if (fm[x] + fs[x] + 1 >= k) {
			fm[x] = fs[x] = 0;
			++res;
		} else {
			if (fm[y] < fm[x] + 1)
				fs[y] = fm[y], fm[y] = fm[x] + 1;
			else if (fs[y] < fm[x] + 1)
				fs[y] = fm[x] + 1;
		}
	}
	
	return res;
}

void main() {
	read(n);
	int siz = sqrt(n * __lg(n));
	
	for (int i = 1, x, y; i < n; ++i) {
		read(x, y);
		AddEdge(x, y), AddEdge(y, x);
	}
	
	Dfs(1, 0);
	
	for (int k = 1; k <= n; ++k) {
		if (k <= siz) writewith(Solve(k), '\n');
		else {
			int ans = Solve(k);
			int l = k, r = n;
			
			while (l <= r) {
				int mid = (l + r) >> 1;
				
				if (Solve(mid) != ans) r = mid - 1;
				else l = mid + 1;
			}
			
			for (int i = k; i <= r; ++i)
				writewith(ans, '\n');
			
			k = r;
		}
	}
}
}

signed main() {
    Hanx16qwq::main();
    return 0;
}

标签:paths,Given,int,Tree,样例,tree,CF1039D,read,fm
From: https://www.cnblogs.com/hanx16msgr/p/17056005.html

相关文章

  • React Tree树形结构封装工具类
    需要依赖 immutable,用于groupby分组buildTree为入口方法,注意返回的是Immutable.List对象,使用需要调用.toJS()方法转为普通对象其中 creatNode方法为构建节点对象,可根......
  • 24.PyQt5【高级组件】树形组件-QTreeWidget
    一、前言QTreeWidget使用类似于QListView类的方式提供一种典型的基于item的树形交互方法类,该类基于QT的“模型/视图”结构,提供了默认的模型来支撑item的显示,这些i......
  • 30. CF-Hamiltonian Spanning Tree
    题目链接给出一个点数为\(n\)的无向完全图,所有边的长度均为\(y\),然后指定该图的一个生成树,将树中的长度改为\(x\),求该图最短的哈密顿路径的长度。先分类讨论,对于\(x......
  • Google's B-tree挺快
    #if0#include"set.h"//github.com/Kronuz/cpp-btreeusingnamespacebtree;#else#include<set>//en.cppreference.com/w/cpp/container/multiset#endif#incl......
  • Potree 003 基于Potree Desktop创建自定义工程
    1、第三方js库第三方库js库选择dojo,其官网地址为https://dojotoolkit.org/,git地址为https://github.com/dojo/dojo,demo地址为https://demos.dojotoolkit.org/demos/,如果打......
  • 「AGC018F」Two Trees
    题目点这里看题目。给定两棵树\(A,B\),两棵树均包含\(n\)个结点。结点编号均从\(1\simn\)。现在需要给每个编号分配一个权值,使得两棵树上的任意子树内,所有的结点编......
  • 【luogu CF1707D】Partial Virtual Trees(容斥)(DP)
    PartialVirtualTrees题目链接:luoguCF1707D题目大意给你一棵以1为根的数,问你对于每个长度,有多少个点集序列,第一个点集是全部点,最后一个点集只有1号点,且中间每个点......
  • 【题解】CF893F Subtree Minimum Query
    那个……令姐……能以成亲为前提……和我交往吗(娇羞)集训完刚好开方舟春活,并且我刚好攒够了给令姐买衣服的石头,这真的是巧合吗?思路各种做法,但是有强化版。首先是naive......
  • treemap与hashcode
    有个需求 需要将map排序 我就用了treemap 一个map列表  将总计字段放在最后面 其他无所谓 最开始是这样写的Map<String,Object>temp=newTreeMap<>(ne......
  • 【题解】P6071 『MdOI R1』Treequery
    海浪尽头的你啊,到底何时归来?额滴就木异象啊……思路清真树论。树论地考虑祖先后代关系,分讨一下。用ST表处理一下\(lca(l,r)=u\):\(u,p\)无祖先后代关系,答案......