Hdu 5401 Persistent Link/cut Tree 树上分治/记忆化搜索
来源:互联网 发布:linux signal函数 编辑:程序博客网 时间:2024/06/06 16:45
Persistent Link/cut Tree
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 535 Accepted Submission(s): 163
Problem Description
Teacher Mai has m+1 trees, T0,T1,⋯,Tm . T0 consists one vertex numbered 0 .
He generated theTi in this way. Get a copy of Tai and Tbi . Add an edge with length li between vertex numbered ci in T′ai and di in T′bi . Relabel the vertices in the new tree. Let k be the number of vertices in T′ai . He keeps labels of vertices in T′ai the same, and adds k to labels of vertices in T′bi .
If there is a treeT with n vertices v0,v1,v2,⋯,vn−1 , F(T)=∑n−1i=0∑n−1j=i+1d(vi,vj) (d(vi,vj) means the distance between the vi and vj ).
For everyi(1≤i≤m) , he wants to know F(Ti) .
He generated the
If there is a tree
For every
Input
There are multiple test cases(about 100 ).
For each test case, the first line contains one numberm(1≤m≤60) , the following are m lines. The i -th lines contains five numbers ai,bi,ci,di,li(0≤ai,bi<i,0≤li≤109) . It's guarenteed that there exists a vertex numbered ci in Tai and there exists a vertex numbered di in Tbi .
For each test case, the first line contains one number
Output
For each test case, print F(Ti) modulo 109+7 in the i -th line.
Sample Input
30 0 0 0 21 1 0 0 42 2 1 0 3
Sample Output
228216
Author
xudyh
Source
2015 Multi-University Training Contest 9
树上问题。
第0次合并时只有1棵一个节点的树,接着每次操作都把之前第 a[i]、b[i]次合并后的两棵树上编号c[i] d[i]的节点用长度为l[i]的一条边合并,第b[i]棵树上的点编号全部加上第a[i]棵树上节点的个数。就这样不断合并。
问你每次合并后所有树上路径的长度之和。
分治,把每棵树不断拆分成之前求过的树,并把每次搜到的答案用map记录下来。
具体实现详见代码注释。
好题啊!
十分简单易懂(...),我只看了一晚上就看懂了。
#include <cstdio>#include <iostream>#include <string.h>#include <string> #include <map>#include <queue>#include <vector>#include <set>#include <algorithm>#include <math.h>#include <cmath>#include <stack>#include <utility>#define mem0(a) memset(a,0,sizeof(a))#define meminf(a) memset(a,0x3f,sizeof(a))#define pll pair<ll,ll>typedef long long ll;typedef long double ld;using namespace std;const int maxn=65,inf=0x3f3f3f3f; const ll llinf=0x3f3f3f3f3f3f3f3f,mod=1e9+7; const ld pi=acos(-1.0L);ll a[maxn],b[maxn],c[maxn],d[maxn],l[maxn],size[maxn],msize[maxn],ans[maxn];//记忆化搜索,把搜索过的答案储存起来 map<pll,ll> q[maxn]; //存储第i棵树j到k的距离 map<ll,ll> mp[maxn]; //存储第i棵树所有点到编号为k的节点的距离 ll getlen(int i,ll now,ll k) { //计算第i棵树中编号now到编号k的距离 if (now>k) swap(now,k);if (q[i].count(pll(now,k))) return q[i][pll(now,k)];if (k<size[a[i]]) //若两个节点都在第a[i]棵树当中,继续递归 return q[i][pll(now,k)]=getlen(a[i],now,k);if (now>=size[a[i]]) //若两个节点都在第b[i]棵树当中,继续递归 return q[i][pll(now,k)]=getlen(b[i],now-size[a[i]],k-size[a[i]]);//若节点不在同一棵子树,距离为now到a[i]经过l[i]到b[i]再到k的距离 return q[i][pll(now,k)]=(getlen(a[i],now,c[i])+l[i]+getlen(b[i],k-size[a[i]],d[i]))%mod;}ll getsum(int i,ll now) { //计算第i棵树所有点到编号为now的距离和 if (mp[i].count(now)) return mp[i][now];if (now<size[a[i]]) return mp[i][now]=(getsum(a[i],now)+(l[i]+getlen(a[i],now,c[i]))*msize[b[i]]%mod+getsum(b[i],d[i]))%mod;//对第i棵树,同样地拆分成两棵树,计算now到所属子树所有点的距离、对面子树所有节点对答案的贡献 //其中,假设now属于第a[i]棵子树,对面子树b[i]所有节点对答案的贡献=b[i]所有节点到d[i]的距离+b[i]所有节点经过l[i]到a[i]再到c[i]的距离//若now属于b[i],则反之亦然 else return mp[i][now]=(getsum(b[i],now-size[a[i]])+(l[i]+getlen(b[i],now-size[a[i]],d[i]))*msize[a[i]]+getsum(a[i],c[i]))%mod;}int main() { int n;while (scanf("%d",&n)!=EOF) {int i,j;for (i=0;i<=60;i++) {mp[i].clear();q[i].clear();}q[0][pll(0,0)]=0;mp[0][0]=0;size[0]=msize[0]=1;ans[0]=0; for (i=1;i<=n;i++) {scanf("%lld%lld%lld%lld%lld",&a[i],&b[i],&c[i],&d[i],&l[i]);size[i]=size[a[i]]+size[b[i]];msize[i]=size[i]%mod;ans[i]=ans[a[i]]+ans[b[i]]+((l[i]*msize[a[i]])%mod)*msize[b[i]]%mod+msize[b[i]]*getsum(a[i],c[i])%mod+msize[a[i]]*getsum(b[i],d[i])%mod;//合并之后答案为两棵树各自内部的答案贡献+路径端点分别在两棵子树上的贡献 //其中,路径端点分别在两棵树上的贡献=新增加的边l[i]的贡献+对方子树节点数*c[i],d[i]号节点到各自子树所有节点距离和 ans[i]%=mod;printf("%lld\n",ans[i]);}}return 0;}
阅读全文
0 0
- Hdu 5401 Persistent Link/cut Tree 树上分治/记忆化搜索
- HDU 5401 Persistent Link/cut Tree
- hdu 5401 Persistent Link/cut Tree
- [hdu 5401] Persistent Link/cut Tree
- 动态规划,计数DP,模拟(Persistent Link/cut Tree,HDU 5401)
- 树上记忆化搜索(Crazy Bobo,HDU 5325)
- 【link-cut tree】
- Link Cut Tree (paint)
- link-cut-tree
- Link-Cut Tree
- Link/cut tree
- BZOJ2157【Link Cut Tree】
- 【笔记】Link-Cut-Tree
- (link-cut tree)
- Link-Cut-Tree总结
- Link/Cut Tree
- Link-Cut-Tree模板
- Link-Cut-Tree讲解
- JAVA单例模式
- ES内存那点事
- 一:数据结构
- http get post 慢速攻击
- 带你了解----->BFC
- Hdu 5401 Persistent Link/cut Tree 树上分治/记忆化搜索
- RESTful
- 数据库乐观锁
- 图片上传预览原理及实现
- face ++ 实现人脸识别
- ZigBee CC2530 Z-Stack 18 单播通信1-16位地址模式
- cenots6.8部署java项目时用到的部分命令
- 你家的小程序那么优秀,快来这里进行海量曝光!
- boost静态断言记录