线段树84分求助
查看原帖
线段树84分求助
86624
洛谷Onlinejudge楼主2020/7/13 16:24
#include "bits/stdc++.h"
using namespace std;
#define MAXT 2000000
#define MAXN 505000

inline int Read(void){
	int X=0,Y=1;char C=getchar();
	while(C<'0'||C>'9'){if(C=='-'){Y=-1;}C=getchar();}
	while('0'<=C&&C<='9'){X=X*10+(C-'0');C=getchar();}
	return X*Y;
}

inline int LeftSon(int i){return i<<1;}
inline int RightSon(int i){return i<<1|1;}

struct SegmentTree{
	int Left,Right,Max;
}Tree[MAXT];

struct EDGE{
	int Next,To,Dis;
}E[MAXN*3];
int Head[MAXN*3],Size;

void Add(int From,int To,int Dis){
	E[++Size].Next=Head[From];
	E[Size].Dis=Dis;
	Head[From]=Size;
	E[Size].To=To;
	return;
}

int N,M;
queue <int> Queue;
bool Visited[MAXN];
int Dis[MAXN],MaxDis,Root,F[MAXN],Pre[MAXN];
inline void BFS(int Start,bool ISNT){
	Queue.push(Start);
	Visited[Start]=true;
	Dis[Start]=0;
	while(!Queue.empty()){
		int From=Queue.front();
		Queue.pop();
		for(register int i=Head[From];i;i=E[i].Next){
			int To=E[i].To,JDis=E[i].Dis;
			if(Visited[To]==true)
				continue;
			Dis[To]=Dis[From]+JDis;
			if(MaxDis<Dis[To]){
				MaxDis=Dis[To];
				if(ISNT==false)Root=To;
			}
			if(ISNT==true){
				Pre[From]=E[i].Dis;
				F[To]=From;
			}
			Visited[To]=true;
			Queue.push(To);
		}
	}
	return;
}

int Dia[MAXN],Count;
int MinSum=1<<30,MaxTot;
int Node[MAXN],PZ[MAXN];
int InPut[MAXN];

void DFS(int Start,int Top){
	Dis[Top]=0;
	for(register int i=Head[Start];i;i=E[i].Next){
		int To=E[i].To,JDis=E[i].Dis;
		if(Visited[To]==true||To==Top)
			continue;
		Visited[To]=true;
		Dis[To]=JDis+Dis[Start];
		InPut[Top]=max(InPut[Top],Dis[To]);
		DFS(To,Top);
	}
	return;
}

inline void Build(int i,int Left,int Right){
	Tree[i].Left=Left;
	Tree[i].Right=Right;
	if(Left==Right){
		Tree[i].Max=InPut[Node[Left]];
		return;
	}
	int Mid=(Left+Right)>>1;
	int L=LeftSon(i),R=RightSon(i);
	Build(L,Left,Mid),Build(R,Mid+1,Right);
	Tree[i].Max=max(Tree[L].Max,Tree[R].Max);
	return;
}

inline int Search(int i,int Left,int Right){
	if(Left>Tree[i].Right||Tree[i].Left>Right)
		return 0;
	if(Left<=Tree[i].Left&&Tree[i].Right<=Right)
		return Tree[i].Max;
	int M=0;
	int L=LeftSon(i),R=RightSon(i);
	if(Tree[L].Right>=Left)
		M=max(M,Search(L,Left,Right));
	if(Tree[R].Left<=Right)
		M=max(M,Search(R,Left,Right));
	return M;
}

int main(void){
	N=Read(),M=Read();
	for(register int i=1;i<N;i++){
		int From=Read(),To=Read(),Dis=Read();
		Add(From,To,Dis),Add(To,From,Dis);
	}
	BFS(1,false),MaxDis=0;
	for(register int i=1;i<=N;i++)
		Dis[i]=0,Visited[i]=false;
	BFS(Root,true);
	for(register int i=1;i<=N;i++)
		if(Dis[i]==MaxDis)
			Dia[++Count]=i;
	MinSum=1<<30;
	for(register int Q=1;Q<=Count;Q++){
		int From=Dia[Q],Len=0;
		for(register int i=1;i<=N;i++)
			Visited[i]=false,InPut[i]=0,Dis[i]=0,PZ[i]=0;
		while(From!=Root){
			Node[++Len]=From;
			Visited[From]=true;
			From=F[From];
		}
		PZ[1]=0;
		Node[++Len]=Root;
		Visited[Len]=true;
		for(register int i=1;i<=Len;i++){
			if(i>1)
				PZ[i]=PZ[i-1]+Pre[Node[i]];
			DFS(Node[i],Node[i]);
		}
		MaxTot=0;
		Build(1,1,Len);
		int Left=1,Right=1;
		while(Right<=Len){
			while((PZ[Right]-PZ[Left])>M&&Left<=Right)
				Left++;
			if(Left>Right)Left=Right;
			MaxTot=max(PZ[Left],PZ[Len]-PZ[Right]);
			MaxTot=max(MaxTot,Search(1,Left,Right));
			MinSum=min(MinSum,MaxTot);
			Right++;
		}
	}
	cout<<MinSum<<endl;
	return 0;
}
2020/7/13 16:24
加载中...