[清华集训2016]汽水

[清华集训2016]汽水

UOJ
BZOJ
这是一个常数大的人过不了的算法
分数规划套点分治,暴力离散化然后树状数组查询
复杂度:\(O(nlog^3n)\)
所以有大佬教我卡卡常嘛??

#define lb(i) (i&-i)
#define ll long long
#include<bits/stdc++.h>
using namespace std;
const int _=5e4+5;
const ll inf=1e18;
inline ll re(){
    ll x=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*w;
}
int n,num,cnt,tot,rt,Rt,ok;
int h[_],ms[_],sz[_],vis[_];
ll k,l,r=inf,mid,ans;
ll val[_],o[_<<1],f[_],g[_],t[_<<1];
vector<int>son[_];
struct edge{int to,next;ll w;}e[_<<1];
inline void link(int u,int v,ll w){
	e[++cnt]=(edge){v,h[u],w},h[u]=cnt;
	e[++cnt]=(edge){u,h[v],w},h[v]=cnt;
}
inline void add(int i,ll v){while(i<=num)t[i]=max(t[i],v),i+=lb(i);}
inline void mdf(int i,ll v){while(i<=num)t[i]=v,i+=lb(i);}
inline ll qmax(int i){ll res=-inf;while(i)res=max(res,t[i]),i-=lb(i);return res;}
void qrt(int u,int fa){
	sz[u]=1,ms[u]=0;
	for(int i=h[u];i;i=e[i].next){
		int v=e[i].to;
		if(v==fa||vis[v])continue;
		qrt(v,u),sz[u]+=sz[v],
		ms[u]=max(ms[u],sz[v]);
	}
	ms[u]=max(ms[u],tot-sz[u]);
	if(ms[u]<ms[rt])rt=u;
}
void bu(int u){
	vis[u]=1;int now=tot;
	for(int i=h[u];i;i=e[i].next){
		int v=e[i].to;
		if(vis[v])continue;
		if(sz[u]<sz[v])tot=now-sz[u];
		else tot=sz[v];rt=0,qrt(v,0);
		son[u].push_back(rt);bu(rt);
	}
}
void dfs(int u,int fa,int dep,ll dis){
	val[u]=dis+dep*mid;
	f[u]=o[++num]=dis-dep*mid;
	g[u]=o[++num]=-f[u];
	for(int i=h[u];i;i=e[i].next){
		int v=e[i].to;
		if(v==fa||vis[v])continue;
		dfs(v,u,dep+1,dis+e[i].w);
	}
}
void calc(int u,int fa){
	g[u]=lower_bound(o+1,o+num+1,g[u])-o;
	if(qmax(g[u]-1)+val[u]>0)ok=1;
	for(int i=h[u];i;i=e[i].next){
		int v=e[i].to;
		if(v^fa&&!vis[v])calc(v,u);
	}
}
void pre(int u,int fa){
	f[u]=lower_bound(o+1,o+num+1,f[u])-o;
	add(f[u],val[u]);
	for(int i=h[u];i;i=e[i].next){
		int v=e[i].to;
		if(v^fa&&!vis[v])pre(v,u);
	}
}
void clear(int u,int fa){
	mdf(f[u],-inf);
	for(int i=h[u];i;i=e[i].next){
		int v=e[i].to;
		if(v^fa&&!vis[v])clear(v,u);
	}
}
void solve(int u){
	vis[u]=1;num=0;
	dfs(u,0,0,0);
	sort(o+1,o+num+1);
	num=unique(o+1,o+num+1)-o-1;
	f[u]=lower_bound(o+1,o+num+1,0)-o;
	add(f[u],0);
	for(int i=h[u];i;i=e[i].next){
		int v=e[i].to;if(vis[v])continue;
		calc(v,u);if(ok)return;pre(v,u);
	}
	mdf(f[u],-inf);
	for(int i=h[u];i;i=e[i].next){
		int v=e[i].to;
		if(!vis[v])clear(v,u);
	}
	for(int i=h[u],j=0;i;i=e[i].next){
		int v=e[i].to;if(ok)return;
		if(!vis[v])solve(son[u][j++]);
	}
}
int main(){
    tot=ms[0]=n=re();k=re();
	for(int i=1;i<n;++i){
		int u=re(),v=re();ll w=re()-k;
		link(u,v,w);r=min(r,abs(w))+1;
	}
	qrt(1,0);bu(Rt=rt);
	while(l<=r){
		mid=(l+r)>>1;
		memset(vis,0,sizeof(vis));
		memset(t,-0x7f,sizeof(t));
		ok=0;solve(Rt);
		if(ok)ans=r=mid-1;
		else l=mid+1;
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2018-12-06 14:16  sdzwyq  阅读(247)  评论(0编辑  收藏  举报