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

猜你喜欢

转载自www.cnblogs.com/asuldb/p/12174399.html