• ●BZOJ 2500 幸福的道路


    题链:

    http://www.lydsy.com/JudgeOnline/problem.php?id=2500

    题解:

    DFS,单调队列


    首先有一个结论,距离树上某一个点最远的点一定是树的直径的一个端点。


    然后就3个DFS求出直接并得到D[i]数组表示i点到最远的点的距离。


    然后就用两个单调队列分别维护一个单减的最大值和一个单增的最小值,

    以便求出以i位置结尾的最长合法区间。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 1000500
    #define rint register int
    using namespace std;
    struct Edge{
    	int to[MAXN*2],val[MAXN*2],nxt[MAXN*2],head[MAXN],ent;
    	Edge(){ent=2;}
    	void Adde(int &u,int &v,int &w){
    		to[ent]=v; val[ent]=w; nxt[ent]=head[u]; head[u]=ent++;
    		to[ent]=u; val[ent]=w; nxt[ent]=head[v]; head[v]=ent++;
    	}
    }E;
    int D[MAXN];
    int N,M,d1,d2,val;
    char gc(){
    	//return getchar();
    	static char s[300005];
    	static int bit=300000,p=0,len=0;
    	if(p>=len) len=fread(s,1,bit,stdin),s[len]=EOF,p=0;
    	return s[p++];
    }
    void read(int &x){
    	static int sn; static char ch;
    	x=0; sn=1; ch=gc();
    	while(ch<'0'||'9'<ch){if(ch=='-')sn=-1;ch=gc();}
    	while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    	x=x*sn;
    }
    void cmax(int &a,int b){
    	if(a<b) a=b;
    }
    void dfs(int u,int fa,int len,int &d){
    	if(len>=val) d=u,val=len;
    	cmax(D[u],len);
    	for(int i=E.head[u];i;i=E.nxt[i]){
    		if(E.to[i]==fa) continue;
    		dfs(E.to[i],u,len+E.val[i],d);
    	}
    }
    int solve(){
    	static int qmx[MAXN],qmn[MAXN],lmx=1,rmx=0,lmn=1,rmn=0,ANS=0,p=1;
    	for(int i=1;i<=N;i++){
    		while(lmx<=rmx&&D[qmx[rmx]]<=D[i]) rmx--;
    		while(lmn<=rmn&&D[qmn[rmn]]>=D[i]) rmn--;
    		qmx[++rmx]=i; qmn[++rmn]=i;
    		while(D[qmx[lmx]]-D[qmn[lmn]]>M){
    			if(qmx[lmx]<qmn[lmn]) p=qmx[lmx]+1,lmx++;
    			else p=qmn[lmn]+1,lmn++;
    		}
    		cmax(ANS,i-p+1);
    	}
    	return ANS;
    }
    int main(){
    	read(N); read(M); 
    	for(rint i=2,f,d;i<=N;i++)
    		read(f),read(d),E.Adde(f,i,d);
    	val=0; dfs(1,0,0,d1);
    	val=0; dfs(d1,0,0,d2);
    	val=0; dfs(d2,0,0,d1);
    	printf("%d",solve());
    	return 0;
    }
    

      

  • 相关阅读:
    linux开发中常用的命令及技巧(连载)
    使用CCS调试基于AM335X的SPL、Uboot(原创)
    [C语言]变量的声明和定义有什么区别
    C语言中void*详解及应用
    使用中断处理程序实现loop功能
    原码,反码,补码的深入理解与原理
    关于C和C++不同源文件中重名变量的问题(转)
    const extern static 终极指南(转)
    函数调用栈分析
    16位和32位的80X86汇编语言的区别(转)
  • 原文地址:https://www.cnblogs.com/zj75211/p/8168860.html
Copyright © 2020-2023  润新知