【CF150E】 Freezing with Style

题目

中位数显然是可以二分的,我们二分一个\(mid\),所有边权不小于\(mid\)设成\(1\),否则设为\(-1\);如果能找到一条边权和不小于\(0\)的路径,就说明中位数可以更大;于是这显然可以长链剖分+线段树

第一次写长剖线段树,就当写个板子了

代码

#include<bits/stdc++.h>
#define re register
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
const int maxn=1e5+5;
inline int read() {
	char c=getchar();int x=0;while(c<'0'||c>'9')c=getchar();
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct node{int mx,t;}a[maxn*3];
int l[maxn*3],r[maxn*3],tag[maxn*3];
struct E{int v,nxt,w;}e[maxn<<1];
int dfn[maxn],len[maxn],son[maxn],head[maxn];
int n,num,L,R,rx,ry,X,Y,flag,__,val[maxn],wt[maxn];
inline void add(int x,int y,int w) {
	e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=w;
}
void dfs1(int x,int fa) {
	for(re int i=head[x];i;i=e[i].nxt) {
		if(e[i].v==fa) continue;dfs1(e[i].v,x);
		if(len[e[i].v]>len[son[x]]) son[x]=e[i].v,wt[x]=e[i].w;
	}
	len[x]=len[son[x]]+1;
}
void dfs2(int x) {
	dfn[x]=++__;if(!son[x])return;dfs2(son[x]);
	for(re int i=head[x];i;i=e[i].nxt)if(!dfn[e[i].v])dfs2(e[i].v);
}
inline node operator+(const node &A,const node &B) {return A.mx>B.mx?A:B;}
void build(int x,int y,int i) {
	l[i]=x,r[i]=y;if(x==y)return;
	int mid=x+y>>1;build(x,mid,i<<1),build(mid+1,y,i<<1|1);
}
void clr(int i) {
	tag[i]=a[i].t=0;a[i].mx=-n;
	if(l[i]==r[i])return;clr(i<<1),clr(i<<1|1);
}
inline void mix(int i,int v) {tag[i]+=v;a[i].mx+=v;}
inline void pushdown(int i) {
	if(!tag[i])return;
	mix(i<<1,tag[i]),mix(i<<1|1,tag[i]);tag[i]=0;
}
node qry(int x,int y,int i) {
	if(x<=l[i]&&y>=r[i])return a[i];int mid=l[i]+r[i]>>1;pushdown(i);
	if(y<=mid)return qry(x,y,i<<1);if(x>mid)return qry(x,y,i<<1|1);
	return qry(x,y,i<<1)+qry(x,y,i<<1|1);
}
void chg(int x,int y,int v,int i) {
	if(x<=l[i]&&y>=r[i]) {mix(i,v);return;}
	int mid=l[i]+r[i]>>1;pushdown(i);
	if(x<=mid)chg(x,y,v,i<<1);if(y>mid)chg(x,y,v,i<<1|1);
	a[i]=a[i<<1]+a[i<<1|1];
}
void mof(int pos,int i,node v) {
	if(l[i]==r[i]) {a[i]=a[i]+v;return;}
	int mid=l[i]+r[i]>>1;pushdown(i);
	if(pos<=mid)mof(pos,i<<1,v);else mof(pos,i<<1|1,v);a[i]=a[i<<1]+a[i<<1|1];
}
void Dfs(int x,int fa,int mid) {
	if(flag)return;
	mof(dfn[x],1,(node){0,x});if(!son[x])return;
	Dfs(son[x],x,mid);
	chg(dfn[x]+1,dfn[x]+len[x]-1,wt[x]>=mid?1:-1,1);
	if(L<len[x]) {
		node ask=qry(dfn[x]+L,dfn[x]+min(len[x]-1,R),1);
		if(ask.mx>=0) {flag=1;X=x,Y=ask.t;return;}
	}
	for(re int i=head[x];i;i=e[i].nxt) {
		if(e[i].v==fa||e[i].v==son[x])continue;Dfs(e[i].v,x,mid);
		int v=(e[i].w>=mid?1:-1);
		for(re int j=1;j<=len[e[i].v];++j) {
			node c=qry(dfn[e[i].v]+j-1,dfn[e[i].v]+j-1,1);
			c.mx+=v;if(L-j>=len[x]||j>R) continue;
			node ask=qry(dfn[x]+max(0,L-j),dfn[x]+min(len[x]-1,R-j),1);
			if(ask.mx+c.mx>=0) {X=c.t,Y=ask.t;flag=1;return;}
		}
		for(re int j=1;j<=len[e[i].v];++j) {
			node c=qry(dfn[e[i].v]+j-1,dfn[e[i].v]+j-1,1);
			c.mx+=v;mof(dfn[x]+j,1,c);
		}
	}
}
inline int chk(int mid) {
	clr(1);flag=0;Dfs(1,0,mid);return flag;
}
int main() {
	n=read(),L=read(),R=read();
	for(re int x,y,w,i=1;i<n;i++) {
		x=read(),y=read(),w=read();
		add(x,y,w),add(y,x,w);val[i]=w;
	} 
	dfs1(1,0);dfs2(1);build(1,n,1);std::sort(val+1,val+n);
	int rr=std::unique(val+1,val+n)-val-1,ll=1;
	while(ll<=rr) {
		int mid=ll+rr>>1;
		if(chk(val[mid])) {
			ll=mid+1;rx=X,ry=Y;
		}
		else rr=mid-1;
	}
	printf("%d %d\n",rx,ry);return 0;
}
posted @ 2020-01-10 08:04  asuldb  阅读(224)  评论(2编辑  收藏  举报