LINK:心上秋

唐多令 宋 吴文英

何处合成愁。离人心上秋。纵芭蕉,不雨也飕飕。都道晚凉天气好,有明月,怕登楼。

年事梦中休。花空烟水流。燕辞归,客尚淹留。垂柳不萦裙带住。漫长是,系行舟。

心上秋 笔下梅 笙中月。

此题 求树上任意两点之间的最长不下降子序列 权值集合为{1~5}.

\(n<=30000,m<=300000\)

考虑暴力 把链抽出来然后暴力dp.最长不下降子序列的dp是nlogn的 所以总复杂度为nlognm.

优化暴力 发现权值集合很小 把链抽出来之后 设f[i][j]表示到达第i个点权值为j的最长长度 多了一个五倍的常数不过复杂度O(n) 总复杂度nm.

考虑优化 如果权值集合只有1,2怎么办?

不妨考虑倍增 设f[i][j][k][w]表示从i跳到2^j的祖先经过的边的权值从k到w的最长不降子序列的长度。

发现这个东西可以合并.

对于所有数据我们可以倍增预处理出这个数组。

对于某个询问(x,y) 我们先让x调到lca累计一个数组g[k]表示小于等于k的路径的最长长度 然后再从lca跳到y即可。

跟保卫王国的倍增dp有点像 不过我没写过那道题的倍增dp 回来可以看一下 值得一提的是这道题没有修改 所以就简单了很多。

我觉得树剖不太能写的样子 矩阵不是很好维护.

我写的有点繁琐了。大体上有一个坑点:注意g数组的维护要维护某个区间的答案 初始化和转移要注意。

在最后求答案的时候也注意由lca跳向y的时候要反着做. 数组下标也得反着.所以g数组也要有一个反着的值.

通过这道题 我们发现可以扩展到序列上 如求某段序列的最长不下降子序列 也可以使用这种倍增的方法来做。

可见倍增是优化dp的一种常用手段。

const int MAXN=30010;
int n,m,len,maxx,ans;
int ql[MAXN],qr[MAXN],wl[MAXN],wr[MAXN],top1,top2;
int g[MAXN][16][6][6],f[MAXN][16],Log[MAXN],d[MAXN],w[MAXN][6];
int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1],e[MAXN<<1];
inline void add(int x,int y,int z)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
e[len]=z;
}
inline void dfs(int x,int father)
{
d[x]=d[father]+1;
f[x][0]=father;
rep(1,Log[d[x]],i)
{
f[x][i]=f[f[x][i-1]][i-1];
rep(1,maxx,k)
rep(1,maxx,w)
{
int s1=min(k,w),s2=max(k,w);
rep(s1,s2,l)g[x][i][k][w]=max(g[x][i][k][w],g[x][i-1][k][l]+g[f[x][i-1]][i-1][l][w]);
}
}
go(x)
{
if(tn==father)continue;
rep(e[i],maxx,j)rep(1,e[i],k)g[tn][0][j][k]=g[tn][0][k][j]=1;
dfs(tn,x);
}
}
inline void LCA(int x,int y)
{
top1=top2=0;
if(d[x]>d[y])
{
fep(Log[d[x]],0,i)
{
if(d[f[x][i]]>=d[y])
{
ql[++top1]=x;
wl[top1]=i;
x=f[x][i];
}
}
}
if(d[y]>d[x])
{
fep(Log[d[y]],0,i)
{
if(d[f[y][i]]>=d[x])
{
qr[++top2]=y;
wr[top2]=i;
y=f[y][i];
}
}
}
if(x==y)return;
fep(Log[d[x]],0,i)
{
if(f[x][i]!=f[y][i])
{
ql[++top1]=x;
wl[top1]=i;
x=f[x][i];
qr[++top2]=y;
wr[top2]=i;
y=f[y][i];
}
}
ql[++top1]=x;
wl[top1]=0;
qr[++top2]=y;
wr[top2]=0;
}
inline void get_ans()
{
ans=0;
rep(1,top1,i)
{
rep(1,maxx,j)w[i][j]=0;
rep(1,maxx,j)
rep(1,j,k)w[i][j]=max(w[i][j],w[i-1][k]+g[ql[i]][wl[i]][k][j]);
}
int l=top2;
rep(top1+1,top2+top1,i)
{
rep(1,maxx,j)w[i][j]=0;
rep(1,maxx,j)
rep(1,j,k)w[i][j]=max(w[i][j],w[i-1][k]+g[qr[l]][wr[l]][j][k]);
--l;
}
rep(1,maxx,i)ans=max(ans,w[top1+top2][i]);
}
int main()
{
freopen("1.in","r",stdin);
get(n);
rep(2,n,i)
{
int x,y,z;
get(x);get(y);get(z);
maxx=max(maxx,z);
add(x,y,z);add(y,x,z);
Log[i]=Log[i>>1]+1;
}
dfs(1,0);
get(m);
rep(1,m,i)
{
int x,y;
get(x);get(y);
LCA(x,y);
get_ans();
put(ans);
}
return 0;
}

最新文章

  1. JavaScript对UNIX时间戳的转换
  2. Hive Over HBase
  3. 受限玻尔兹曼机(RBM)学习笔记(八)RBM 的评估
  4. android之调用webservice 实现图片上传
  5. MobilePhone正则表达式
  6. hdu1047(模拟大量的循环添加)
  7. Android之SurfaceView学习
  8. python中的迭代
  9. 挖一下插件v1.5版本发布
  10. PHP判断变量是否为空的几种方法小结
  11. oracle drop table(表)数据恢复方法
  12. pybind11 安装
  13. 服务器与客户端连接 &amp; 聊天机器人
  14. centos7安装NFS
  15. fiddler不能抓某些的包的原因
  16. HDU 1171 01背包
  17. bzoj1026
  18. OO第四次课程总结分析
  19. 使用JavaScript动态更改CSS样式
  20. java中package import区别

热门文章

  1. DLL隐式链接
  2. Hyperledger Fabric 2.1 搭建教程
  3. 解决IOS端微信浏览器input,textarea有内上边框阴影
  4. Windows分页文件设置不当导致SQL Server服务被终止
  5. 各种jar包下载地址
  6. PJzhang:python基础入门的7个疗程-seven
  7. 设计模式:Adapter模式
  8. java8中parallelStream提升数倍查询效率是怎样实现的,来看看这篇文章
  9. 轻松应对并发问题,简易的火车票售票系统,Newbe.Claptrap 框架用例,第一步 —— 业务分析
  10. 题解 洛谷 P3639 【[APIO2013]道路费用 】