1. 程式人生 > >●BZOJ 2500 幸福的道路

●BZOJ 2500 幸福的道路

pos -s log for struct com problem string spa

題鏈:

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;
}

  

●BZOJ 2500 幸福的道路