题意:求一颗树上三点距离两两相等的三元组对数

n<=1e5

思路:From https://blog.bill.moe/bzoj4543-hotel/

f[i][j]表示以i为根的子树中距离i为j的点的个数

g[i][j]表示以i为根的子树中两点距离他们的lca为d,lca距离i为d-j的两点对数

g[i][j]找到一个子树外的f[i][j]就对答案有贡献

朴素的方程为:设v为u的一个儿子

ans+=f[u][j]*g[v][j+1]+g[u][j]*f[y][j-1]

g[u][j+1]+=f[u][j+1]*f[v][j]

g[u][j-1]+=g[v][j]

f[u][j+1]+=f[v][j]

显然f[i][j]只和深度有关,且f[u]的[1,len[u]]这一段是所有f[v]的[0,len[u]-1]右移一位之和

为了防止同一个子树中的信息算多了,先算ans部分再执行后面三步更新

指针的写法我完全是抄的

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef pair<ll,int>P;
#define N 100010
#define M 200010
#define fi first
#define se second
#define MP make_pair
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1 const ll MOD=1e9+,inv2=(MOD+)/;
double eps=1e-;
int INF=<<;
ll inf=5e13;
int dx[]={-,,,};
int dy[]={,,-,}; int head[M],vet[M],nxt[M],tot;
int len[N],son[N];
ll tmp[N*],*f[N],*g[N],*now=tmp,ans; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} void add(int a,int b)
{
nxt[++tot]=head[a];
vet[tot]=b;
head[a]=tot;
} void dfs(int u,int fa,int d)
{
len[u]=;
int e=head[u];
while(e)
{
int v=vet[e];
if(v!=fa)
{
dfs(v,u,d+);
if(len[v]>len[son[u]])
{
son[u]=v;
len[u]=len[v]+;
}
}
e=nxt[e];
}
} void solve(int u,int fa)
{
if(son[u])
{
f[son[u]]=f[u]+;
g[son[u]]=g[u]-;
solve(son[u],u);
}
f[u][]=;
ans+=g[u][];
int e=head[u];
while(e)
{
int v=vet[e];
if(v!=fa&&v!=son[u])
{
f[v]=now;
now+=(len[v]<<)+;
g[v]=now;
now+=(len[v]<<)+;
solve(v,u);
rep(j,,len[v])
{
if(j) ans+=f[u][j-]*g[v][j];
ans+=g[u][j+]*f[v][j];
}
rep(j,,len[v])
{
g[u][j+]+=f[u][j+]*f[v][j];
if(j) g[u][j-]+=g[v][j];
f[u][j+]+=f[v][j];
}
}
e=nxt[e];
}
}
int main()
{
int n=read();
tot=;
rep(i,,n-)
{
int x=read(),y=read();
add(x,y);
add(y,x);
}
len[]=-;
dfs(,,);
ans=;
f[]=now,now+=(len[]<<)+,g[]=now,now+=(len[]<<)+;
solve(,);
printf("%lld\n",ans);
return ;
}

【BZOJ3522&BZOJ4543】Hotel加强版(长链剖分,树形DP)的更多相关文章

  1. bzoj4543 [POI2014]Hotel加强版 长链剖分+树形DP

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4543 题解 这道题的弱化版 bzoj3522 [POI2014]Hotel 的做法有好几种吧. ...

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

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

  3. BZOJ.4543.[POI2014]Hotel加强版(长链剖分 树形DP)

    题目链接 弱化版:https://www.cnblogs.com/SovietPower/p/8663817.html. 令\(f[x][i]\)表示\(x\)的子树中深度为\(i\)的点的个数,\( ...

  4. BZOJ3522&4543 [POI2014]Hotel加强版 长链剖分

    上上周见fc爷用长链剖分秒题 于是偷偷学一学 3522的数据范围很小 可以暴力枚举每个点作为根节点来dp 复杂度$O(n^2)$ 考虑令$f[x][j]$表示以$x$为根的子树内距离$x$为$j$的点 ...

  5. 【BZOJ4543】[POI2014]Hotel加强版 长链剖分+DP

    [BZOJ4543][POI2014]Hotel加强版 Description 同OJ3522数据范围:n<=100000 Sample Input 7 1 2 5 7 2 5 2 3 5 6 ...

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

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

  7. CF1009F Dominant Indices——长链剖分优化DP

    原题链接 \(EDU\)出一道长链剖分优化\(dp\)裸题? 简化版题意 问你每个点的子树中与它距离为多少的点的数量最多,如果有多解,最小化距离 思路 方法1. 用\(dsu\ on\ tree\)做 ...

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

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

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

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

  10. bzoj 3522 / 4543 [POI 2014] Hotel - 动态规划 - 长链剖分

    题目传送门 bzoj 3522 需要root权限的传送点 bzoj 4543 快速的传送点 慢速的传送点 题目大意 给定一棵树,问有多少个无序三元组$(x, y, z)$使得这三个不同点在树上两两距离 ...

随机推荐

  1. 九个console命令调试JS

    下面九个console命令,可以帮助我们更方便地调试 常用的console命令,最常用的事console.log() 1 //常用的console命令,其中最常用的console.log() 2 co ...

  2. shell脚本一一项目3

    主题:批量创建100个用户并设置密码 脚本内容 user_list=$@user_file=./user.infofor USER in ${user_list};do if ! id $USER & ...

  3. LeetCode 114. Flatten Binary Tree to Linked List 动态演示

    把二叉树先序遍历,变成一个链表,链表的next指针用right代替 用递归的办法先序遍历,递归函数要返回子树变成链表之后的最后一个元素 class Solution { public: void he ...

  4. 基于K-means Clustering聚类算法对电商商户进行级别划分(含Octave仿真)

    在从事电商做频道运营时,每到关键时间节点,大促前,季度末等等,我们要做的一件事情就是品牌池打分,更新所有店铺的等级.例如,所以的商户分入SKA,KA,普通店铺,新店铺这4个级别,对于不同级别的商户,会 ...

  5. SAP smartforms打印数据出框线或跟框线重叠,但是预览是正常的

    如图,打印内容压在框线上,但是打印预览是正常的 预览图如下,预览是正常的 预览用PDF!命令,导出PDF,也是正常的,就直接打印有问题,不是打印机的问题,用Adobe PDF打印机也是不行 如果只有一 ...

  6. [Linux] 024 IP 地址配置和网络 yum 源

    1. IP 地址配置 (1) 使用 setup 工具 $ setup ps setup 是 RedHat 系列的功能:一般地,Debian系列没有这个功能 Xubuntu 没有这个功能 (2) 启动网 ...

  7. POJ-1287.Network(Kruskal + Prim + Prim堆优化)

    Networking Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19674   Accepted: 10061 Desc ...

  8. [CF804F]Fake bullions

    Solution: ​ 这题可以分为两个部分, ​ 一个部分为处理出每个点最大的金条数与最小的金条数,记为 \([Min_i, Max_i]\) ​ 第二部分为对于 \(n\) 个变量 \(x_i\i ...

  9. 06 CAS的原理和AQS

    CAS的原理 CAS(compareAndSwap),比较交换,是一种无锁的原子算法. Cas(value,expect,newValue),如果vaule和ecpect一样,就更新为newValue ...

  10. 【学习总结】gcc和gdb

    目录 <> vim.gcc.gdb: gcc: gcc和g++是c/c++的linux系统集成的编译器,源文件的后缀应为 .C/.cpp/.c++/.cc等 编译器可以将C.C++等语言源 ...