原题链接

\(EDU\)出一道长链剖分优化\(dp\)裸题?

简化版题意

问你每个点的子树中与它距离为多少的点的数量最多,如果有多解,最小化距离

思路

方法1.

用\(dsu\ on\ tree\)做到\(O(nlogn)\)

方法2.

考虑\(dp\),也就是设\(f[u][d]\)表示以\(u\)为根的子树中有多少个点与它的距离为\(j\),则转移如下:

\(f[u][0]=1\),\(f[u][d]+=f[v][d-1]\)

发现可以直接通过把数组右移直接把一个儿子的信息继承过来,又因为转移是跟深度相关的,那么我们直接把长儿子的信息继承过来就好了,然后暴力合并短儿子的信息

这样的时间复杂度都是\(O(n)\)的,怎么证明?直接继承长儿子的信息通过指针可以做到\(O(1)\),然后每条长链只会在顶端被合并,而长链的长度和是\(O(n)\),于是总复杂度就\(O(n)\)啦

空间复杂度的证明同理

代码如下

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
#include <ctime>
#include <queue>
#include <map>
#include <set> using namespace std; #define IINF 0x3f3f3f3f3f3f3f3fLL
#define ull unsigned long long
#define pii pair<int, int>
#define uint unsigned int
#define mii map<int, int>
#define lbd lower_bound
#define ubd upper_bound
#define INF 0x3f3f3f3f
#define vi vector<int>
#define ll long long
#define mp make_pair
#define pb push_back #define N 1000000 struct Edge {
int next, to;
}e[2*N+5]; int n;
int head[N+5], eid, len[N+5], longson[N+5];
int memory[N+5], ans[N+5]; void addEdge(int from, int to) {
e[++eid].next = head[from];
e[eid].to = to;
head[from] = eid;
} void dfs1(int u, int fa) {
for(int i = head[u], v; i; i = e[i].next) {
v = e[i].to;
if(v == fa) continue;
dfs1(v, u);
if(len[longson[u]] < len[v]) longson[u] = v;
}
len[u] = len[longson[u]]+1;
} void dp(int u, int fa, int *f) {
ans[u] = 0;
f[0] = 1;
int *g;
if(longson[u]) {
g = f+1;
dp(longson[u], u, g);
if(g[ans[longson[u]]] > f[ans[u]] || (g[ans[longson[u]]] == f[ans[u]] && ans[longson[u]] < ans[u]))
ans[u] = ans[longson[u]]+1;
}
g = f+len[u];
for(int i = head[u], v; i; i = e[i].next) {
v = e[i].to;
if(v == fa || v == longson[u]) continue;
dp(v, u, g);
for(int j = 1; j <= len[v]; ++j) {
f[j] += g[j-1];
if(f[j] > f[ans[u]] || (f[j] == f[ans[u]] && j < ans[u]))
ans[u] = j;
}
}
} int main() {
scanf("%d", &n);
for(int i = 1, x, y; i < n; ++i) {
scanf("%d%d", &x, &y);
addEdge(x, y), addEdge(y, x);
}
dfs1(1, 0);
dp(1, 0, memory);
for(int i = 1; i <= n; ++i) printf("%d\n", ans[i]);
return 0;
}

CF1009F Dominant Indices——长链剖分优化DP的更多相关文章

  1. CF1009F Dominant Indices 长链剖分

    题目传送门 https://codeforces.com/contest/1009/problem/F 题解 长链剖分的板子吧. 令 \(dp[x][i]\) 表示 \(x\) 的子树中的深度为 \( ...

  2. 【CF1009F】Dominant Indices(长链剖分优化DP)

    点此看题面 大致题意: 设\(d(x,y)\)表示\(x\)子树内到\(x\)距离为\(y\)的点的个数,对于每个\(x\),求满足\(d(x,y)\)最大的最小的\(y\). 暴力\(DP\) 首先 ...

  3. 2019.01.19 bzoj3653: 谈笑风生(长链剖分优化dp)

    传送门 长链剖分优化dpdpdp水题. 题意简述:给一棵树,mmm次询问,每次给一个点aaa和一个值kkk,询问满足如下条件的三元组(a,b,c)(a,b,c)(a,b,c)的个数. a,b是c的祖先 ...

  4. 长链剖分优化dp三例题

    首先,重链剖分我们有所认识,在dsu on tree和数据结构维护链时我们都用过他的性质. 在这里,我们要介绍一种新的剖分方式,我们求出这个点到子树中的最长链长,这个链长最终从哪个儿子更新而来,那个儿 ...

  5. Codeforces 1009 F. Dominant Indices(长链剖分/树上启发式合并)

    F. Dominant Indices 题意: 给一颗无向树,根为1.对于每个节点,求其子树中,哪个距离下的节点数量最多.数量相同时,取较小的那个距离. 题目: 这类题一般的做法是树上的启发式合并,复 ...

  6. CF 1009 F Dominant Indices —— 长链剖分+指针

    题目:http://codeforces.com/contest/1009/problem/F 也可以用 dsu on tree 的做法,全局记录一个 dep,然后放进堆里,因为字典序要最小,所以再记 ...

  7. 2018.11.03 NOIP模拟 树(长链剖分优化dp)

    传送门 考虑直接推式子不用优化怎么做. 显然每一个二进制位分开计算贡献就行. 即记录fi,jf_{i,j}fi,j​表示距离iii这个点不超过jjj的点的每个二进制位的0/10/10/1个数. 但直接 ...

  8. BZOJ4543[POI2014]Hotel加强版——长链剖分+树形DP

    题意参见BZOJ3522 n<=100000 数据范围增强了,显然之前的转移方程不行了,那么不妨换一种. 因为不能枚举根来换根DP,那么我们描述的DP方程每个点要计算三个点都在这个点的子树内的方 ...

  9. 长链剖分优化树形DP总结

    长链剖分 规定若\(x\)为叶结点,则\(len[x]=1\). 否则定义\(preferredchild[x]\)(以下简称\(pc[x]\),称\(pc[x]\)为\(x\)的长儿子)为\(x\) ...

随机推荐

  1. linux netstat 查看网络连接状况

    netstat -lnpnetstat -an |grep 127.0.0.1 tcp 0.0.0.0:* LISTEN tcp 0.0.0.0:* LISTEN [root@wang /]# net ...

  2. 磁盘分区知识与linux系统分区实践

    一.磁盘存储逻辑结构图 回忆: (1)什么是分区? 磁盘分区就相当于给磁盘打隔断. (2)磁盘在linux里的命名 IDE    /dev/hda  hdb SCSI   sda     sdb 分区 ...

  3. JavaSE基础(八)--Java 循环结构

    Java 循环结构 - for, while 及 do...while 顺序结构的程序语句只能被执行一次.如果您想要同样的操作执行多次,,就需要使用循环结构. Java中有三种主要的循环结构: whi ...

  4. Java编程思想(二)一切都是对象

    2.1用句柄操纵对象 尽管一切都看作是对象,但是操纵的标识符实际上是指向一个对象的“句柄”(handdle): 拥有一个句柄并不表示必须有一个对象同他连接: String  s:   这里创建的只是句 ...

  5. [转帖]电源ac和dc有什么区别_dc ac分别代表什么

    电源ac和dc有什么区别_dc ac分别代表什么 发表于 2017-10-28 17:18:58 电源设计应用 +关注 http://m.elecfans.com/article/571712.htm ...

  6. oracle授予权限

    CONNECT角色:    --是授予最终用户的典型权利,最基本的 CREATE    SESSION    --建立会话 RESOURCE角色:    --是授予开发人员的    CREATE    ...

  7. Python+requests维持会话

    Python+requests维持会话 一.使用Python+requests发送请求,为什么要维持会话? 我们是通过http协议来访问web网页的,而http协议是无法维持会话之间的状态.比如说我们 ...

  8. 剑指offer43:左旋转字符串(字符串):对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。

    1 题目描述 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=”a ...

  9. 消息服务百科全书——为什么使用MQ

    为什么要使用MQ?有如下几个好处: 解耦 在项目启动之初来预测将来项目会碰到什么需求,是极其困难的.消息系统在处理过程中间插入了一个隐含的.基于数据的接口层,两边的处理过程都要实现这一接口.这允许你独 ...

  10. JAVA对存储过程的调用方法(本文源于网络)

    博客分类: java java存储过程sql  一:Java如何实现对存储过程的调用:   A:不带输出参数的   ---------------不带输出参数的-------------------- ...