• UOJ276 【清华集训2016】汽水


    Link
    先点分治,保存下以当前重心为一端且不经过其它中重心的路径,并按(overline w-k)排序。
    然后二分答案,用双指针扫每个重心的路径,并维护下(overline w-k)最小的路径。
    注意不能选来自同一子树的两条路径,因此我们再维护一个与(overline w-k)最小的路径来自不同子树的(overline w-k)最小的路径即可。

    #include<cstdio>
    #include<algorithm>
    typedef long long i64;
    const int N=50007,M=1000007;
    int n,tot=1,All,root,cnt,num,head[N],ver[N<<1],next[N<<1],vis[N<<1],size[N],mx[N],st[N],ed[N];
    i64 k,edge[N<<1],val[M];
    struct node{i64 l;int d,r;}t[2][M];
    int operator<(node a,node b){return a.l<b.l;}
    int read(){int x;scanf("%d",&x);return x;}
    i64 raed(){i64 x;scanf("%lld",&x);return x;}
    void add(){int u=read(),v=read();i64 w=raed();ver[++tot]=v,next[tot]=head[u],edge[tot]=w,head[u]=tot,ver[++tot]=u,next[tot]=head[v],edge[tot]=w,head[v]=tot;}
    void findroot(int u,int fa)
    {
        size[u]=1,mx[u]=0;
        for(int i=head[u],v;i;i=next[i]) if(!vis[i]&&(v=ver[i])^fa) findroot(v,u),size[u]+=size[v],mx[u]=std::max(mx[u],size[v]);
        mx[u]=std::max(mx[u],All-size[u]),root=mx[u]<mx[root]? u:root;
    }
    void dfs(int u,int fa,i64 a,int b,int c)
    {
        t[0][++num]=node{a,b,c},t[1][num]=node{-a,b,c};
        for(int i=head[u],v;i;i=next[i]) if(!vis[i]&&(v=ver[i])^fa) dfs(v,u,a+edge[i]-k,b+1,c);
    }
    void solve(int u)
    {
        int id=++cnt;
        st[id]=num+1;
        for(int i=head[u];i;i=next[i]) if(!vis[i]) dfs(ver[i],u,edge[i]-k,1,ver[i]);
        ed[id]=num;
        for(int i=0;i<2;++i) std::sort(t[i]+st[id],t[i]+ed[id]+1);
        for(int i=head[u],v;i;i=next[i]) if(!vis[i]) vis[i^1]=1,mx[0]=All=size[v=ver[i]],findroot(v,root=0),solve(root);
    }
    int check(i64 lim)
    {
        for(int i=0;i<2;++i)
        {
    	for(int j=1;j<=num;++j)
    	{
    	    val[j]=-t[i][j].l-lim*t[i][j].d;
    	    if(t[i][j].l<=0&&val[j]<0) return 1;
    	}
    	for(int j=1;j<=cnt;++j)
    	{
    	    int id1=0,id2=0;i64 mx1,mx2;
    	    for(int l=st[j],r=ed[j],p=l,q=r;q>=l;--q)
    	    {
    		for(;p<=r&&t[i][q].l+t[i][p].l<=0;++p)
    		{
    		    int id=t[i][p].r;i64 x=val[p];
    		    if(id1==id) { if(mx1>x) mx1=x; }
    		    else if(!id1||mx1>x) id2=id1,mx2=mx1,id1=id,mx1=x;
    		    else if(!id2||mx2>x) id2=id,mx2=x;
    		}
    		if(id1&&id1^t[i][q].r&&val[q]+mx1<0) return 1;
    		if(id2&&id2^t[i][q].r&&val[q]+mx2<0) return 1;
    	    }
    	}
        }
        return 0;
    }
    int main()
    {
        n=read(),k=raed();i64 l=1,r=1e13;
        for(int i=1;i<n;++i) add();
        mx[0]=All=n,findroot(1,0),solve(root);
        for(i64 mid;l<=r;) check(mid=(l+r)>>1)? r=mid-1:l=mid+1;
        printf("%lld",r);
    }
    
  • 相关阅读:
    C++ Primer Plus 6 第二章
    C++ Primer Plus 6 第一章
    log4j不同级别的日志打印到不同的目录
    清理(删除)pika中的数据
    大数据技术发展回顾
    Flink RedisRichSinkFunction
    Flink FlinkEnvBuilder
    Flink maven project build config
    RedisRichSinkFunction
    kafka Consumer2Local
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12305676.html
Copyright © 2020-2023  润新知