HDU 5401 Persistent Link/cut Tree
来源:互联网 发布:微信 积分 源码下载 编辑:程序博客网 时间:2024/05/29 07:29
考虑爆搜,树i生成后,两两点对路径分成两部分,一部分不经过中间的边,那么就是
那么转化为计算在树i中,所有点到某个点j的距离和。假设j在
这样就化成了在树i中两个点j和k的距离,如果在同一棵子树中,可以递归下去,否则假设j在
然后对两类询问全都记忆化搜索即可。
接着考虑计算一下复杂度。
对于第二类询问,可以考虑询问的过程类似于线段树,只会有两个分支,中间的部分已经记忆化下来,不用再搜,时间复杂度
我们分析一下复杂度,首先对于第一类询问,在
所以每个询问复杂度是
这里的离散化姿势特别不舒服,但是据队友说,不这样写会TLE….虽然觉得应该不会吧
// whn6325689// Mr.Phoebe// http://blog.csdn.net/u013007900#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#include <functional>#include <numeric>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define eps 1e-9#define PI acos(-1.0)#define INF 0x3f3f3f3f#define LLINF 1LL<<62#define speed std::ios::sync_with_stdio(false);typedef long long ll;typedef unsigned long long ull;typedef long double ld;typedef pair<ll, ll> pll;typedef complex<ld> point;typedef pair<int, int> pii;typedef pair<pii, int> piii;typedef vector<int> vi;#define CLR(x,y) memset(x,y,sizeof(x))#define CPY(x,y) memcpy(x,y,sizeof(x))#define clr(a,x,size) memset(a,x,sizeof(a[0])*(size))#define cpy(a,x,size) memcpy(a,x,sizeof(a[0])*(size))#define mp(x,y) make_pair(x,y)#define pb(x) push_back(x)#define lowbit(x) (x&(-x))#define MID(x,y) (x+((y-x)>>1))#define ls (idx<<1)#define rs (idx<<1|1)#define lson ls,l,mid#define rson rs,mid+1,r#define root 1,1,ntemplate<class T>inline bool read(T &n){ T x = 0, tmp = 1; char c = getchar(); while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar(); if(c == EOF) return false; if(c == '-') c = getchar(), tmp = -1; while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar(); n = x*tmp; return true;}template <class T>inline void write(T n){ if(n < 0) { putchar('-'); n = -n; } int len = 0,data[20]; while(n) { data[len++] = n%10; n /= 10; } if(!len) data[len++] = 0; while(len--) putchar(data[len]+48);}//-----------------------------------const int MOD=1e9+7;int n,m;int idx[150];ll num[66];set<ll> pos[66];vector<ll> g[66];ll dis[66][150][150];ll todis[66][150];ll dp[66];struct QUERRY{ int a,b; ll c,d,l; void input() { read(a),read(b),read(c),read(d),read(l); }} t[66];//离散化int discre(int i,ll b){ return lower_bound(g[i].begin(),g[i].end(),b)-g[i].begin();}//离散化的初始准备void init(){ for(int i=m; i>=1; i--) { for(set<ll>::iterator it=pos[i].begin(); it!=pos[i].end(); it++) { if(*it>=num[t[i].a]) pos[t[i].b].insert(*it-num[t[i].a]); else pos[t[i].a].insert(*it); g[i].pb(*it); } } for(set<ll>::iterator it=pos[0].begin(); it!=pos[0].end(); it++) g[0].pb(*it);}//只维护了上三角ll getdist(int v,int l,int r){ if(l<=r)return dis[v][l][r]; return dis[v][r][l];}ll solve(int v){ int le=t[v].a,ri=t[v].b; ll num1=num[le]%MOD,num2=num[ri]%MOD; int len=g[v].size(); //子树的贡献 dp[v]=(dp[le]+dp[ri])%MOD; //新加边的贡献 dp[v]=(dp[v]+(num1*num2%MOD)*t[v].l%MOD)%MOD; //其他节点到连接节点的贡献 int lec=discre(le,t[v].c); int rid=discre(ri,t[v].d); dp[v]=(dp[v]+todis[le][lec]*num2%MOD+todis[ri][rid]*num1%MOD)%MOD; //分别在两棵子树上面离散化 for(int i=0; i<len; i++) { if(g[v][i]<num[le]) idx[i]=discre(le,g[v][i]); else idx[i]=discre(ri,g[v][i]-num[le]); } //更新整棵树到出节点的距离 for(int i=0; i<len; i++) { if(g[v][i]<num[le]) todis[v][i]=(todis[le][idx[i]]+todis[ri][rid]+num2*(t[v].l+getdist(le,lec,idx[i]))%MOD)%MOD; else todis[v][i]=(todis[ri][idx[i]]+todis[le][lec]+num1*(t[v].l+getdist(ri,rid,idx[i]))%MOD)%MOD; } //更新连出点之间的距离 for(int i=0; i<len; i++) { dis[v][i][i]=0; for(int j=i+1; j<len; j++) { if(g[v][i]<num[le] && g[v][j]<num[le]) dis[v][i][j]=dis[le][idx[i]][idx[j]]; else if(g[v][i]>=num[le]&&g[v][j]>=num[le]) dis[v][i][j]=dis[ri][idx[i]][idx[j]]; else dis[v][i][j]=getdist(le,idx[i],lec)+getdist(ri,idx[j],rid)+t[v].l; dis[v][i][j]%=MOD; } }}int main(){ freopen("data.txt","r",stdin); while(read(m)) { for(int i=0; i<=m; i++) { g[i].clear(); pos[i].clear(); } CLR(num,0); CLR(dp,-1); CLR(todis,0); num[0]=1; dp[0]=0; for(int i=1; i<=m; i++) { t[i].input(); pos[t[i].a].insert(t[i].c); pos[t[i].b].insert(t[i].d); num[i]=num[t[i].a]+num[t[i].b]; } init(); for(int i=0; i<=m; i++) { int len=g[i].size(); for(int j=0; j<len; j++) for(int k=0; k<len; k++) dis[i][j][k]=0; } for(int i=1; i<=m; i++) { solve(i); write(dp[i]),putchar('\n'); } } return 0;}
0 0
- 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)
- Hdu 5401 Persistent Link/cut Tree 树上分治/记忆化搜索
- 【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讲解
- link-cut tree预习
- Github搭建属于自己的开源项目-androd学习之旅(72)
- 50道编程题(有精力的同学看看)
- UIP协议栈二
- Java设计模式-目录
- [leetcode] Binary Tree Paths
- HDU 5401 Persistent Link/cut Tree
- 如何实现Siri中的波纹动画
- 利用Linux LiveCD迁移Windows到SSD硬盘
- 华为OJ平台试题 ——字符串:打印字符串中重复的字符
- 文章标题
- RT-Thread finsh源码分析: finsh_heap.h
- 2015 7 3 java核心技术卷一 7-10章 图形,事件处理,Swing组件和应用程序部署
- Linux下Sublime安装
- spmio内网源部署