• [UOJ UR #4追击圣诞老人]


    来自FallDream的博客,未经允许,请勿转载, 谢谢。


    传送门

    考虑直接维护一个堆,然后往里面丢链,并且取出k个堆顶就行了。

    然后就需要分类讨论啥的,给你的三个点变成两条链,每次取出一条链之后选择权值最小的再劈成两条链丢进去。

    卡空间  所以树剖,不选择倍增

    复杂度O((n+k)logn)

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define MN 500000
    #define N 524288
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    struct data{int x,y;ll X;
        friend bool operator <(const data&x,const data&y){return x.X>y.X;} 
        data operator + (ll y)
        {
            data c=*this;c.X+=y;
            return c;    
        }
    };
    priority_queue<data> q;
    int n,k,w[MN+5],dep[MN+5],head[MN+5],cnt=0,top[MN+5],mx[MN+5];
    int s[MN+5],p[MN+5],fa[MN+5],T[N*2+5],dfn[MN+5],dn=0;
    struct edge{int to,next;}e[MN+5];
    inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;}
    vector<data>v[MN+5];
    int Merge(int x,int y){return w[x]>w[y]?y:x;}
    int query(int l,int r)
    {
        int sum=0;
        for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1)
        {
            if(~l&1) sum=Merge(sum,T[l+1]);
            if( r&1) sum=Merge(sum,T[r-1]);
        }    
        return sum;
    }
    inline int Up(int x,int k)
    {
        int z=dep[x]-k;
        for(;dep[top[x]]>z;x=fa[top[x]]);
        return p[dfn[top[x]]+z-dep[top[x]]];
    }
    int lca(int x,int y)
    {
        for(;top[x]!=top[y];x=fa[top[x]])
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
        return dep[x]<dep[y]?x:y;
    }
    
    pair<int,int> Query(int x,int y)
    {
        int res=0;
        for(;top[x]!=top[y];x=fa[top[x]])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            res=Merge(res,s[x]);
        }    
        if(dfn[x]>dfn[y]) swap(x,y);
        res=Merge(res,query(dfn[x],dfn[y]));
        return make_pair(x,res);
    }
    
    data Insert(int x,int y,ll v)
    {
    //    cout<<"Insert"<<x<<" "<<y<<" "<<v<<endl;
        pair<int,int> z=Query(x,y);
    //    cout<<"CalcOK"<<z.first<<" "<<z.second<<endl;
        return (data){x,y,w[z.second]}+v;    
    }
    
    void Solve(int x,int y,int z,int l,ll Add)
    {
    //    cout<<"Solve"<<x<<" "<<y<<" "<<z<<" "<<l<<" "<<Add<<endl;
        if(z==l)
        {
            if(x!=z) q.push(Insert(x,Up(x,dep[x]-dep[z]-1),Add));
            if(y!=z) q.push(Insert(y,Up(y,dep[y]-dep[z]-1),Add));
            return;    
        }
        if(!(dep[x]>=dep[z]&&Up(x,dep[x]-dep[z])==z)) swap(x,y);
        if(x!=z) q.push(Insert(x,Up(x,dep[x]-dep[z]-1),Add));
        q.push(Insert(fa[z],y,Add));
    }
    
    void Dfs(int x,int tp)
    {
        top[x]=tp;p[dfn[x]=++dn]=x;    
        if(tp==x) s[x]=x; else s[x]=Merge(s[fa[x]],x);
        if(mx[x]) Dfs(mx[x],tp);
        for(int i=head[x];i;i=e[i].next)
            if(e[i].to!=mx[x]) Dfs(e[i].to,e[i].to); 
    }
    
    void Pre(int x)
    {
        top[x]=1;mx[x]=0;
        for(int i=head[x];i;i=e[i].next)
        {
            Pre(e[i].to);
            top[x]+=top[e[i].to];
            if(top[e[i].to]>top[mx[x]]) mx[x]=e[i].to;    
        }
    }
    
    int main()
    {
        n=read();k=read();w[0]=1e9;
        for(int i=1;i<=n;++i) w[i]=read(),q.push((data){i,i,w[i]});
        for(int i=2;i<=n;++i) ins(fa[i]=read(),i),dep[i]=dep[fa[i]]+1;
        Pre(1);Dfs(1,1);
        for(int i=1;i<=n;++i) T[i+N]=p[i];
        for(int i=N;i;--i) T[i]=Merge(T[i<<1],T[i<<1|1]);
        for(int i=1;i<=n;++i) 
        {
            int x=read(),y=read(),z=read();
            if(x==y&&y==z){v[i].push_back((data){x,x,w[x]});continue;}
            if(x==y) swap(x,z);v[i].push_back(Insert(x,y,0));
            if(z==y||z==x) continue;
            int l1=lca(x,z),l2=lca(y,z),L=lca(x,y);
            if(dep[z]<dep[L]) v[i].push_back(Insert(fa[L],z,0));
            else if(z!=l1&&z!=l2)
            {
                if(dep[l1]<dep[l2]) swap(l1,l2);
                int Z=Up(z,dep[z]-dep[l1]-1);    
                v[i].push_back(Insert(z,Z,0));
            }
        }
        for(int i=1;i<=k;++i)
        {
            data x=q.top();q.pop();printf("%lld
    ",x.X);int z=Query(x.x,x.y).second;
            //printf("%d %d %d %d %lld
    ",x.x,x.y,x.l,x.z,x.X);
            Solve(x.x,x.y,z,lca(x.x,x.y),x.X-w[z]);
            for(int j=0;j<v[z].size();++j) q.push(v[z][j]+x.X);
        }
        return 0;
    }
  • 相关阅读:
    python中的深拷贝和浅拷贝
    Andrew NG 机器学习编程作业6 Octave
    Andrew NG 机器学习编程作业5 Octave
    梯度下降算法对比(批量下降/随机下降/mini-batch)
    无监督算法
    深度学习的方差与偏差
    Andrew NG 机器学习编程作业4 Octave
    数据约束
    数据库的查询
    MySQL的入门与使用,sqlyog对数据库,表和数据的管理
  • 原文地址:https://www.cnblogs.com/FallDream/p/uoj53.html
Copyright © 2020-2023  润新知