bzoj4543
来源:互联网 发布:网络实用技术基础答案 编辑:程序博客网 时间:2024/04/27 23:50
题意:
给出一棵树,每条边长度为1。问找三个点,使他们两两距离相等有多少方案。
n<=100000(poi原题为5000)
#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>#include<iostream>#define N 110000#define LL long longusing namespace std;struct node{int y,nex;}a[2*N];LL id,*f[N],*g[N],mem[10*N],ans;int fir[N],len,son[N],dep[N],h[N],mx[N],n,siz[N];void ins(int x,int y){ a[++len].y=y;a[len].nex=fir[x];fir[x]=len;}void dfs(int x,int fa){ dep[x]=dep[fa]+1;mx[x]=x; for(int k=fir[x];k;k=a[k].nex) { int y=a[k].y; if(y==fa) continue; dfs(y,x); if(dep[mx[y]]>dep[mx[son[x]]]) son[x]=y; if(dep[mx[y]]>dep[mx[x]]) mx[x]=mx[y]; } siz[mx[x]]=h[x]=dep[mx[x]]-dep[x]+1;}void creat_mem(){ for(int i=1;i<=n;i++) { if(mx[i]!=i) continue; id+=siz[i]-1; f[i]=&mem[id]; id++; g[i]=&mem[id]; id+=2*siz[i]; id+=2; }}void dp(int x,int fa){ if(mx[x]==x) {f[x][0]=1;return;} dp(son[x],x); f[x]=f[son[x]]-1; g[x]=g[son[x]]+1; ans+=g[x][0]; f[x][0]=1; for(int k=fir[x];k;k=a[k].nex) { int y=a[k].y; if(y==fa || y==son[x]) continue; dp(y,x); for(int i=0;i<=h[y];i++) ans+=f[y][i]*g[x][i+1]; for(int i=1;i<=h[y];i++) ans+=g[y][i]*f[x][i-1]; for(int i=0;i<=h[y];i++) g[x][i+1]+=f[y][i]*f[x][i+1]; for(int i=1;i<=h[y];i++) g[x][i-1]+=g[y][i]; for(int i=0;i<=h[y];i++) f[x][i+1]+=f[y][i]; }}int main(){ scanf("%d",&n); for(int i=1;i<n;i++) { int x,y;scanf("%d%d",&x,&y); ins(x,y);ins(y,x); } dfs(1,0); creat_mem(); dp(1,0); printf("%lld\n",ans); return 0;}
题解:
膜了题解。。太神了转述一下
显然对于每个方案(x,y,z)有且仅有一个点u使得:
1、x,y,z在u的不同子树中
2、x,y,z到u距离相等
考虑这种dp方法(不然没法做)
f[i][j]表示i子树中与i距离为j的点有多少个
g[i][j]表示i子树已经组合好了多少需要i子树外距离为j的一个点的点对
就是这个意思
(x,y)就能对g[i][j]贡献1
尝试对每个点找一个重孩子,即若x子树中最深叶节点在孩子y子树中,y就是x的重孩子。
定义每个点的高度h[x]为到子树中最深叶节点的距离,将沿重孩子走的链叫重链。
考虑那个
对于x的第一个孩子y,我们是不是令f[x][i]=f[y][i-1],g[x][i]=g[y][i+1]?
发现是平移,利用数组的地址是连续的,将f[x][1]的地址指向f[y][0],将g[x][0]的地址指向g[y][1]就能
除了重孩子外的转移用
分析时间复杂度。点x转移的复杂度是
将所有的相加,每个x在父亲处为正,在x处为负就全部抵消了!剩下的1作和就是
由于同一条重链用的是同一个数组,事先给他分配重链长度的连续地址即可。空间复杂度也是点分治怎么做?
- bzoj4543
- [bzoj4543/3522]Hotel
- [bzoj3522][bzoj4543][POI2014]HOTEL
- [bzoj4543] [POI2014]Hotel加强版
- BZOJ4543/BZOJ3522 [POI2014]Hotel加强版
- BZOJ4543: [POI2014]Hotel加强版 长链剖分
- 【XSY1536】【BZOJ3522】【BZOJ4543】【POI2014】Hotel 树形DP 长链剖分 启发式合并
- BZOJ4543/3522: [POI2014]Hotel加强版(洛谷P3565)
- ruby将hash赋值给变量
- join连接
- 头指针和头结点
- CSS3 HTML5学习心得
- java 集合类应用
- bzoj4543
- Android种使用Notification实现通知管理以及自定义通知栏(Notification示例四)
- Android - Emoji表情图文混排
- A1120. Friend Numbers (20)
- 编程题-实现蛇形输出
- Django,ImageFiled 图片请求多APP 图片显示
- Bootstrap框架class="thumbnail"是什么意思?
- Volley返回值乱码
- ”正多边形的逼近“求π的近似值