bzoj3784 树上的路径


传送门

#include 
const int N=500005;
int to[N<<1],edge,Next[N<<1],last[N],siz[N],g,L[N*20],R[N*20],w[N<<1];
int v[N*20],vis[N],cnt,st[N*20][21],lstl,lstr,bit[N*20],n,m,x,y,z;
void add(int x,int y,int z){
	to[++edge]=y;
	Next[edge]=last[x];
	last[x]=edge;
	w[edge]=z;
}
void find(int x,int y,int &g,int nn){
	siz[x]=1;
	int mx=0;
	for (int i=last[x];i;i=Next[i]){
		int u=to[i];
		if (u==y || vis[u]) continue;
		find(u,x,g,nn);
		siz[x]+=siz[u];
		mx=std::max(mx,siz[u]);
	}
	if (mx<=nn/2 && nn-siz[x]<=nn/2) g=x;
} 
void dfs(int x,int y,int dis){
	v[++cnt]=dis,L[cnt]=lstl,R[cnt]=lstr;
	for (int i=last[x];i;i=Next[i]){
		int u=to[i];
		if (u==y || vis[u]) continue;
		dfs(u,x,dis+w[i]);
	}
}
void div(int x){
	vis[x]=1;
	v[++cnt]=0,lstl=cnt;
	for (int i=last[x];i;i=Next[i]){
		int u=to[i];
		if (vis[u]) continue;
		lstr=cnt;
		dfs(u,x,w[i]);
		siz[u]=cnt-lstr;
	}
	for (int i=last[x];i;i=Next[i]){
		int u=to[i];
		if (vis[u]) continue;
		find(u,0,g,siz[u]);
		div(g);
	}
}
void init(){
	for (int i=2;i<=cnt;i++) bit[i]=bit[i>>1]+1;
	for (int i=1;i<=cnt;i++) st[i][0]=i;
	for (int i=1;i<=20;i++)
		for (int j=1;j+(1<v[st[j+(1<v[st[r-(1< q;
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;it.l) q.push(note{t.x,t.l,t.mx-1,RMQ(t.l,t.mx-1)});
		if (t.r>t.mx) q.push(note{t.x,t.mx+1,t.r,RMQ(t.mx+1,t.r)});
	}
}