首页 > 其他分享 >CF771C Bear and Tree Jumps

CF771C Bear and Tree Jumps

时间:2023-06-24 17:00:21浏览次数:54  
标签:ch int Jumps CF771C Tree sum 步数

CF771C Bear and Tree Jumps

link

赛时脑子抽了没想出来,其实思路已经沾边了,但是……唉,还是太菜了 qwq。

题意:

给你一颗有 \(n\) 个点的树,和每次能走的最大步数 \(K\),求所有点对相互到达的最小步数之和。

思路:

首先第一步转化很简单:设点 \(u,v\) 在树上的距离为 \(d\),则 \(u, v\) 相互到达的最小步数就是 \(\lceil \frac{d}{K} \rceil\),因为每次我们都要尽量迈最大步数。这时我们很容易想到一种思路,那就是在 dfs 的过程中,去实现这个“逢 \(K\) 进一”。

我大概是卡在第二步转化的一半处。既然要进位,那我们可以考虑在状态中去记录余数。设状态 \(f_{u, j}\) ,表示所有距离点 \(u\) 距离为 \(j\) 的点的答案和,其中 \(j \in [0, K-1]\),那么第一种转移很明显:

\[f_{u, j} = \sum f_{v, j-1}(j\in[1, K-1]) \]

接下来我们考虑当 \(j = 0\) 时的答案。我们发现,对于距离 \(u\) 不超过 \(K\) 的点,因为必须要跳这一步,所有会产生 \(1\) 的贡献;对于距离超过 \(K\) 的点,则由于又走满了一个 \(K\),故也会产生 \(1\) 的贡献。所以有:

\[f_{u, 0} = \sum (f_{v, K-1}+size_v) \]

于是,我们可以求出根节点到所有的其他节点需要跳的步数和(就是 \(f_{1, 0}\))。

但是,我们要求所有点对。所以第三步转化就是,我们进行换根 dp,转移和上面类似,注意剔除原来的贡献。我们求出以每个点为根的答案 \(g_{u, 0}\),最后的答案就是:

\[\frac{1}{2}\sum_{i = 1}^{n} g_{i, 0} \]

这里除以二是因为我们不考虑节点顺序,所以每对点都重复统计了一次。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+100;

inline int read(){
	int x = 0; char ch = getchar();
	while(ch<'0' || ch>'9'){ch = getchar();}
	while(ch>='0'&&ch<='9'){x = x*10+ch-48; ch = getchar();}
	return x;
}
int head[N], tot = 1;
struct node{
	int nxt, to;
}edge[N<<1];
void add(int u, int v){
	edge[++tot].nxt = head[u];
	edge[tot].to = v;
	head[u] = tot;
}

int n, K;
long long dp[N][7], siz[N], g[N][7];
void dfs1(int u, int fa){
	siz[u] = 1;
	for(int i = head[u]; i; i = edge[i].nxt){
		int v = edge[i].to;
		if(v == fa) continue;
		dfs1(v, u);
		siz[u]+=siz[v];
		for(int j = 1; j<=K; ++j){
			dp[u][j%K] += dp[v][j-1];
			if(j == K) dp[u][0]+=siz[v];
		}
	}
}
void dfs2(int u, int fa){
	for(int i = head[u]; i; i = edge[i].nxt){
		int v = edge[i].to;
		if(v == fa) continue;
		for(int j = 1; j<=K; ++j){
			int ta = j-2;
			if(j==1) ta = K-1;
			g[v][j%K] += (dp[v][j%K]+g[u][j-1]-dp[v][ta]);
			if(j==1) g[v][j%K]-=siz[v];
			if(j==K) g[v][j%K]+=(n-siz[v]);
		}
		dfs2(v, u);
	}
}
long long ans;
int main(){
	n = read(), K = read();
	for(int i = 1; i<n; ++i){
		int u = read(), v = read();
		add(u, v);
		add(v, u);
	}
	dfs1(1, 0);
	for(int i = 0; i<K; ++i){
		g[1][i] = dp[1][i];
	}
	dfs2(1, 0);
	for(int i = 1; i<=n; ++i) ans+=g[i][0];
	printf("%lld\n", ans/2);
	return 0;
}

标签:ch,int,Jumps,CF771C,Tree,sum,步数
From: https://www.cnblogs.com/frostwood/p/17501323.html

相关文章

  • python: Treeview Control binding data using tkinter and ttkbootstrap GUI
     """StudentUI.py读文件类date2023-06-24edit:GeovinDu,geovindu,涂聚文ide:PyCharm2023.1python11"""importdatetimeimportsysimportosfromtkinterimportttkfromtkinterimport*fromtkinter.ttkimport*fromttk......
  • PostgreSQL BTree(B-Link-tree) 索引 基本 实现原理
    文章目录背景BTreeB+TreeB-Link-Tree基本数据结构的插入实现BTreeInsert实现B+TreeInsert实现PostgreSQLBTree实现整体结构BTree索引创建实现_bt_buildadd_bt_uppershutdownBTree查询_bt_search实现BTree插入_bt_doinsert实现_bt_split节点分裂_bt_insert_parentlef......
  • CF932D Tree
    题目链接题目见链接。题解知识点:倍增。注意到,题目其实要求我们,每次要选最近一个权值大于等于自己的祖先,可以看出固定点生成出来的序列是固定的。因此,考虑设\(f_{i,j}\)为从\(j\)出发按规则向上走\(2^i\)次的点,设\(b_{i,j}\)为从\(j\)出发按规则向上走\(2^i\)次的......
  • NC200179 Colorful Tree
    题目链接题目题目描述Atreestructurewithsomecolorsassociatedwithitsverticesandasequenceofcommandsonitaregiven.Acommandiseitheranupdateoperationoraqueryonthetree.Eachoftheupdateoperationschangesthecolorofaspecifiedvert......
  • TreeSaver.js 的工作流程逻辑
    Treesaver是浏览器大小尺寸敏感(size-sensitive)的,会就着当前的浏览器尺寸(browsersize),选用不同的分栏表格(grid)做排版。初始化TreeSaver.js框架的入口源代码在后面可以看到:https://github.com/Treesaver/treesaver/blob/master/src/init.js这里的代码用到了Google开发的JS库:Closur......
  • Win7环境下TreeSaver编译环境的搭配
    首先你需要先搭配出”Win7环境下TreeSaver例子环境的搭配”然后才能继续下一步编译环境。例子环境搭配后,你可以在源代码目录下执行paver命令,搭配例子测试环境,也可以执行paverdebug生成带调试注释信息的treesaver脚本,当然也可以使用paverclean删除生成的文件。这些可以......
  • sourcetree忽略文件
    SourceTree默认使用的是全局缓存配置,这个配置文件在SourceTree–>Preferences–>Git–>GlobalIgnoreList可以看到。如下图:如果想针对某个项目单独做,则请参考下面文章:http://www.ifeegoo.com/git-code-management-dot-gitignore-file-has-no-effect-solution.html 这时......
  • CF383C Propagating tree
    题目链接题目见链接。题解知识点:DFS序,树状数组。我们需要对子树的不同奇偶层加减,用dfn序可以解决子树问题,但是并不能直接分奇偶。一种比较麻烦的思路是,将dfn序分成两个序列,一个是偶数层点序,一个是奇数层点序列,处理两个序列对于某个点作为子树根节点时,开始和结束节点,然后就可......
  • 【vue3】实现el-tree组件
     禾小毅csdn博客【vue3】实现el-tree组件,将不同层级的箭头修改成自定义图标的组件封装及调用【vue3】实现简易的“百度网盘”文件夹的组件封装实现【vue3】实现公共搜索组件,在当前页搜索的路由跳转不能改变当前值的操作,使用bus/event-emitter派发器......
  • linux gpio dev,linux gpio子系统 devicetree中GPIO_ACTIVE_LOW
    一直没怎么理解GPIO_ACTIVE_LOW的作用对于以上的dts你应该再熟悉不过,当然这里不是教你如何使用dts,而是关注gpio和irq最后一个数字可以如何利用。例如rst-gpio的OF_GPIO_ACTIVE_LOW代表什么意思呢?可以理解为低有效。什么意思呢?举个例子,正常情况下,我们需要一个gpio口控制灯,我们认......