考试的时候打了个树链剖分,而且还审错题了,以为是每天找所有点的最长路,原来是每天起点的树上最长路径再搞事情。。

先用dfs处理出来每个节点以他为根的子树的最长链和次长链。(后面会用到)

然后用类似dp的方法把每个节点的最长路径求出来。

下面是具体解释,请思考

以一个节点为例(w为它与父亲节点道路的权值)

一、如果它父亲节点的最长路径不过它

那么它最长路径等于它父亲最长路径+w(自己画图即可理解,往上走的)

它的次长路径等于它的最长链(只能往下走)

二、如果过它

那么它的最长路径有两种可能

①它的最长链

②它父亲的次长路径+w

如果①优,那么它最长路径为①,次长路径为max(它的次长链,②)

如果②优,那么它最长路径为②,次长路径为①

很好理解吧。。。

然后让求最大值与最小值差在m之内的最长子串。

据他们说有O(n)的做法,不过我打了O(nlogn)的打法,跑进了1s,反正O(能过)就行。

我的nlogn是二分答案+单调队列。二分答案去验证,挨个移动,看是否满足条件。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define pos2(i,a,b) for(int i=(a);i>=(b);i--)
int n,m;
#define N 1001000
struct haha
{
	int to,next,w;
};
int read()
{
    int x=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')
        ch=getchar();
    while(ch>='0'&&ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x;
}
haha edge[N*4];
int head[N],cnt=1;
void add(int u,int v,int w)
{
	edge[cnt].w=w;
	edge[cnt].to=v;
	edge[cnt].next=head[u];
	head[u]=cnt++;
}
struct qian
{
	int fir,firch;      int sec,secch;
	int roadfir,roadsec;int roadfirch,roadsecch;
}cun[N];
int fa[N];
void dfs(int now)
{
	for(int i=head[now];i;i=edge[i].next)
	{
		int to=edge[i].to;
		int w=edge[i].w;
		dfs(to);
		if(cun[now].sec<cun[to].fir+w)
		{
			cun[now].sec=cun[to].fir+w;
			cun[now].secch=to;
			if(cun[now].sec>cun[now].fir)
			{
				swap(cun[now].sec,cun[now].fir);
				swap(cun[now].secch,cun[now].firch);
			}
		}
	}
}
void dp(int now,int w)
{
	if(now==1)
	{
		cun[now].roadfir=cun[now].fir;
		cun[now].roadsec=cun[now].sec;
		cun[now].roadfirch=cun[now].firch;
		cun[now].roadsecch=cun[now].secch;
	}
	else
	{
		if(cun[fa[now]].roadfirch!=now)
		{
			cun[now].roadfir=cun[fa[now]].roadfir+w;
			cun[now].roadfirch=fa[now];
			cun[now].roadsec=cun[now].fir;
		}
		else
		{
			if(cun[now].fir>cun[fa[now]].roadsec+w)
			{
				cun[now].roadfir=cun[now].fir;
				cun[now].roadfirch=cun[now].firch;
				cun[now].roadsec=max(cun[now].sec,cun[fa[now]].roadsec+w);
			}
			else
			{
				cun[now].roadfir=cun[fa[now]].roadsec+w;
				cun[now].roadfirch=fa[now];
				cun[now].roadsec=cun[now].fir;
			}
		}
	}
	for(int i=head[now];i;i=edge[i].next)
	{
		int to=edge[i].to;
		int ww=edge[i].w;
		dp(to,ww);
	}
}
int f[N];
int qmax[N],hed,tail;
int qmin[N],beg,ed;
bool find(int val){
    hed=tail=0;
    beg=ed=0;
    for(int i=1;i<=n;i++){
        while(hed<tail&&i-qmax[hed]>=val) hed++;
        while(beg<ed&&i-qmin[beg]>=val) beg++;
        while(hed<tail&&f[qmax[tail-1]]<f[i])   tail--;qmax[tail++]=i;
        while(beg<ed&&f[qmin[ed-1]]>f[i]) ed--;qmin[ed++]=i;
        if(i>=val&&f[qmax[hed]]-f[qmin[beg]]<=m) return true;
    }
    return false;
}
int main()
{
    //freopen("race.in","r",stdin);
    //freopen("race.out","w",stdout);
	n=read();m=read();
	pos(i,2,n)
	{
		int x,y;
		x=read();y=read();
		add(x,i,y);
		fa[i]=x;
	}
	dfs(1);
	dp(1,0);

    for(int i=1;i<=n;i++)
        cout<<cun[i].roadfir<<" "<<cun[i].roadsec<<endl;
	while(1);
    for(int i=1;i<=n;i++)
	   f[i]=cun[i].roadfir;
	int l=1,r=n+1;
	while(l<r-1){
        int mid=l+r>>1;
        if(find(mid))l=mid;
        else r=mid;
    }
    int l=1,r=n+1;
    while(l<r-1)
    {
        int mid=(l+r)>>1;
        if(find(mid))
          l=mid;
        else
          r=mid;
    }   

	cout<<l;
	//while(1);
	return 0;
}

  

[BZOJ 2500]幸福的道路 树形dp+单调队列+二分答案的更多相关文章

  1. (noip模拟二十一)【BZOJ2500】幸福的道路-树形DP+单调队列

    Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...

  2. bzoj2500幸福的道路 树形dp+单调队列

    2500: 幸福的道路 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 434  Solved: 170[Submit][Status][Discuss ...

  3. 【bzoj2500】幸福的道路 树形dp+单调队列

    Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...

  4. 【bzoj2500】幸福的道路 树形dp+倍增RMQ+二分

    原文地址:http://www.cnblogs.com/GXZlegend/p/6825389.html 题目描述 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一 ...

  5. [BZOJ 2500] 幸福的道路

    照例先贴题面(汪汪汪) 2500: 幸福的道路 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 368  Solved: 145[Submit][Sta ...

  6. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

  7. ●BZOJ 2500 幸福的道路

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2500 题解: DFS,单调队列 首先有一个结论,距离树上某一个点最远的点一定是树的直径的一个 ...

  8. 【BZOJ2500】幸福的道路 树形DP+RMQ+双指针法

    [BZOJ2500]幸福的道路 Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的 ...

  9. Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF980F.html 题目传送门 - CF980F 题意 给定一个 $n$ 个节点 $m$ 条长为 $1$ 的边 ...

随机推荐

  1. memcached使用文档

    使用memcached进行内存缓存 通常的网页缓存方式有动态缓存和静态缓存等几种,在ASP.NET中已经可以实现对页面局部进行缓 存,而使用memcached的缓存比ASP.NET的局部缓存更加灵活, ...

  2. 鼠标滚轮图片放大缩小功能,使用layer弹框后不起作用

    今天在项目中遇到的一个问题:点击按钮使用layer弹框弹出一张图片,需要加一个鼠标滚轮放大缩小,图片也跟着放大缩小的功能.于是在网上找了一个demo. DEMO: <!DOCTYPE html ...

  3. iis部署wcf服务过程

    一.在iis网站中添加wcf服务,一直添加到web.config目录即可 二.点击基本设置-->连接为-->特定用户.填写登入电脑的用户名和密码. 三.点击身份验证 四.控制面板,设置防火 ...

  4. 3.MQTT paho

    一.概述 遥测传输 (MQTT) 是轻量级基于代理的发布/订阅的消息传输协议,设计思想是开放.简单.轻量.易于实现.这些特点使它适用于受限环境.例如,但不仅限于此: 网络代价昂贵,带宽低.不可靠. 在 ...

  5. 如何为一个eclipse安装android环境

    据说android已经不再支持android adt-bundle的开发环境了,所以如果继续使用的话,会不再更新 使用eclipse来安装android环境或者使用android studio 但是以 ...

  6. ReactJS基础(续)

    前边的ReactJS基础,我们可以了解到,对于React,可以说是万物皆组件 React的组件应该具有 可组合(Composeable)可重用(Reusable)可维护(Maintainable)的特 ...

  7. Java添加JDBC

    添加JDBC 1.SQL Server SQL Server2005 下载 sqljdbc_4.0 https://www.microsoft.com/en-us/download/details.a ...

  8. tomcat7以上,ajax post参数后台获取不到的问题

    AJAX post传参后台获取不到查询参数. 网上找了各种方法,包括设置content-type,又是把json转成json格式字符串,问题依然存在,但是把post改成get又可以获取到,百思不得其解 ...

  9. MQ的导出备份

    参考链接: http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1312_hub_mq/1312_hub_mq.ht ...

  10. web项目直接在浏览器上访问不需要带.jsp,直接ip地址加项目名 在web.xml里配置

    web.xml最上方 <welcome-file-list> <welcome-file> /view/login.jsp </welcome-file> < ...