[2016北京集训试题7]thr-[树形dp+树链剖分+启发式合并]
Description

Solution
神仙操作orz。
首先看数据范围,显然不可能是O(n2)的。(即绝对不是枚举那么简单的),我们考虑dp。
定义f(x,k)为以x为根的子树中与x距离为k的节点数;g(x,k)为在以x为根的子树中选择两个点,使得另一个点应在x子树外且离x距离为k的方案数(或者距离为0)。但是这样子暴力转移怕是会崩em,考虑优化。
这里的树是棵静态树,考虑树链剖分,点分治之类的思想。
最后,由于很多时候它的复杂度和树的高度有关,考虑长链剖分。
转移的话,暴力枚举所有轻链(啊我可能说的不是很清楚,类似启发式合并的想法吧)。
那么该点对应的长链怎么办呢?类似树剖的重儿子,我们定义节点x的长儿子为son[x],它是只有一个的。
而假如该点只有一个儿子,f(x,k)=f(son[x],k-1),g(x,k)=g(son[x],k+1)。
还是和树剖一样的思想,我们把同一条长链的信息存在一起,例如把f(son[x],k-1)的信息与f(x,k)存在同一个地址下。(我们能这么做是因为son[x]的信息在被x更新完后它就没用了啊)。g的话同理。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=;
int mxdep[N],top[N],fa[N],dep[N],son[N],cnt_f[N],cnt_g[N],cntf=,cntg=;
ll F[N],G[N<<];
int getlen(int x){return mxdep[x]-dep[x]+;}
ll &f(int x,int y){return F[cnt_f[top[x]]+dep[x]-dep[top[x]]+y];}
ll &g(int x,int y){return G[cnt_g[top[x]]-dep[x]+dep[top[x]]+y];}
struct _pas{int y,nxt;}_g[N<<];int h[N],tot=;
void dfs1(int x,int f)
{
fa[x]=f;dep[x]=dep[f]+;mxdep[x]=dep[x];son[x]=;
for (int i=h[x];i;i=_g[i].nxt)
if (_g[i].y!=f){
dfs1(_g[i].y,x);
mxdep[x]=max(mxdep[x],mxdep[_g[i].y]);
if (mxdep[son[x]]<mxdep[_g[i].y]) son[x]=_g[i].y;
}
}
void dfs2(int x)
{
top[x]=son[fa[x]]==x?top[fa[x]]:x;
if (top[x]==x)
{
int d=getlen(x);
cnt_f[x]=cntf;cnt_g[x]=cntg+d;
cntf+=d;cntg+=*d;
}
if (son[x]) dfs2(son[x]);
for (int i=h[x];i;i=_g[i].nxt)
if (_g[i].y!=son[x]&&_g[i].y!=fa[x]) dfs2(_g[i].y);
}
ll ans;
void dp(int u)
{
f(u,)=;
if (son[u]) dp(son[u]),ans+=g(u,);
for (int i=h[u];i;i=_g[i].nxt)
if (_g[i].y!=son[u]&&_g[i].y!=fa[u])
{
int v=_g[i].y;dp(v);int len=getlen(v);
for (int i=;i<=len;i++) ans+=g(u,i)*f(v,i-);
for (int i=;i<len;i++) ans+=g(v,i)*f(u,i-);
for (int i=;i<=len;i++) g(u,i)+=f(u,i)*f(v,i-);
for (int i=;i<=len-;i++) g(u,i)+=g(v,i+);
for (int i=;i<=len;i++) f(u,i)+=f(v,i-);
}
}
void _clear()
{
tot=cntf=cntg=;
memset(h,,sizeof(h));
memset(F,,sizeof(F));
memset(G,,sizeof(G));
}
int n,x,y;
int main()
{
while ()
{
scanf("%d",&n);
if (!n) return ;
_clear();
for (int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
_g[++tot]=_pas{y,h[x]};h[x]=tot;
_g[++tot]=_pas{x,h[y]};h[y]=tot;
}
ans=;
dfs1(,);dfs2();dp();
printf("%lld\n",ans);
}
}
[2016北京集训试题7]thr-[树形dp+树链剖分+启发式合并]的更多相关文章
- 【BZOJ3522】【BZOJ4543】【POI2014】Hotel 树形DP 长链剖分 启发式合并
题目大意 给你一棵树,求有多少个组点满足\(x\neq y,x\neq z,y\neq z,dist_{x,y}=dist_{x,z}=dist_{y,z}\) \(1\leq n\leq 1 ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
- 6.3 省选模拟赛 Decompose 动态dp 树链剖分 set
LINK:Decompose 看起来很难 实际上也很难 考验选手的dp 树链剖分 矩阵乘法的能力. 容易列出dp方程 暴力dp 期望得分28. 对于链的情况 容易发现dp方程可以转矩阵乘法 然后利用线 ...
- BZOJ4712洪水——动态DP+树链剖分+线段树
题目描述 小A走到一个山脚下,准备给自己造一个小屋.这时候,小A的朋友(op,又叫管理员)打开了创造模式,然后飞到 山顶放了格水.于是小A面前出现了一个瀑布.作为平民的小A只好老实巴交地爬山堵水.那么 ...
- acm 2015北京网络赛 F Couple Trees 树链剖分+主席树
Couple Trees Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/problemset/problem/123 ...
- [2016北京集训试题8]连在一起的幻想乡[dp+无向图计数]
Description Solution 本博客参考yww大佬的博客,为了加深理解我就自己再写一遍啦. 以下的“无向图”均无重边无自环. 定义f0[n]为n个点构成的无向图个数,f1[n]为n个点构成 ...
- [2016北京集训试题15]cot-[分块]
Description Solution 如图,假如我们知道了以任何一个点为顶点的135-180度的前缀和和90-180度的前缀和,我们就可以搞出三角形的面积. 差分.add[i][j]和dev[i] ...
- [2016北京集训试题15]项链-[FFT]
Description Solution 设y[i+k]=y[i]+n. 由于我们要最优解,则假如将x[i]和y[σ[i]]连线的话,线是一定不会交叉的. 所以,$ans=\sum (x_{i}-y_ ...
- [2016北京集训试题14]股神小D-[LCT]
Description Solution 将(u,v,l,r)换为(1,u,v,l)和(2,u,v,r).进行排序(第4个数为第一关键字,第1个数为第二关键字).用LCT维护联通块的合并和断开.(维护 ...
随机推荐
- Mysql不带条件更新报错
执行命令SET SQL_SAFE_UPDATES = 0;修改下数据库模式即可: 恢复安全模式:SET SQL_SAFE_UPDATES = 1;
- 马克飞象markdown用法
目录 markdown用法 ### 根据标题生成目录 `` 快捷键 ctrl+k 代码区域 ctrl+2 二级标题 ctrl+b/i 粗体/斜体 ctrl+l 插入链接 ctrl+g 插入图片 ctr ...
- Spyder中figure显示设置
Spyder是Python的一个IDE.和其他的Python的IDE相比,它最大的优点就是模仿MATLAB的“工作空间”的功能,可以很方便地观察和修改数组的值. 如果不是进行大规模的工程开发,重点专注 ...
- 1、Spring Cloud - 微服务简介
前言: 业界大牛马丁.福勒(Martin Fowler) 这样描述微服务: 论文网址:https://martinfowler.com/articles/microservices.html 就目前而 ...
- 27、springboot整合RabbitMQ(1)
RabbitMQ整合 使用dockers下载带management的版本,该版本是带web界面的,可操作性比较强
- Kali-linux使用Easy-Creds工具攻击无线网络
Easy-Creds是一个菜单式的破解工具.该工具允许用户打开一个无线网卡,并能实现一个无线接入点攻击平台.Easy-Creds可以创建一个欺骗访问点,并作为一个中间人攻击类型运行,进而分析用户的数据 ...
- Kali-linux使用社会工程学工具包(SET)
社会工程学工具包(SET)是一个开源的.Python驱动的社会工程学渗透测试工具.这套工具包由David Kenned设计,而且已经成为业界部署实施社会工程学攻击的标准.SET利用人们的好奇心.信任. ...
- QTP基本方法
1.for循环: m代表间隔循环长度: 如果m>0,则j要大于i: 如果m<0,则i要大于j: for i to j [step m] 语句块 [exit for]//强制退出循环 nex ...
- SSIS Debug
プロジェクト=>最后一项[DEPJ1200プロパテイページ] 1.配置...=>CreaeDeploymentUtility=True2.デパッグ=>Run64BiRuntime=f ...
- nRF5 SDK for Mesh(六) BLE MESH 的 基础概念
Basic Bluetooth Mesh concepts The Bluetooth Mesh is a profile specification developed and published ...