[APIO2012]派遣

给你一棵树

在进行树形结构时,维护当前节点的左偏树

由于插入是logn的,删除是O(1)的

所以怎么乱搞都没问题

#include<bits/stdc++.h>
#define re return
#define ll long long 
#define inc(i,l,r) for(register int i=l;i<=r;++i)

const int maxn=100005;
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x; 
}

int n,m,fa[maxn],hd[maxn],ls[maxn],rs[maxn],dist[maxn],size[maxn];
ll val[maxn],cost[maxn],ans,C[maxn];

struct node{
    int to,nt;
}e[maxn];

inline int find(int x)
{
    re x==fa[x]?x:fa[x]=find(fa[x]);
}

inline int merge(int x,int y)
{
    if(!x||!y)re x+y;
    
    if(cost[x]<cost[y])swap(x,y);
    
    int &ul=ls[x],&ur=rs[x];
    ur=merge(ur,y);
    fa[ur]=x;
    if(dist[ul]<dist[ur])swap(ul,ur);
    dist[x]=dist[ur]+1;
    C[x]=C[ls[x]]+C[rs[x]]+cost[x];
    size[x]=size[ls[x]]+size[rs[x]]+1;
    re x;
}
inline void dfs(int x)
{
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        dfs(v);
        merge(find(v),find(x));
        while(m<C[find(x)])
        {
            int y=fa[x];
            int z=merge(ls[y],rs[y]);
            fa[y]=fa[z]=z;
        }
    }
    ans=max(ans,val[x]*size[find(x)]);
}

int main()
{
    int x;
    rd(n);rd(m);
    inc(i,1,n)fa[i]=i;
    
    dist[0]=-1;
    inc(i,1,n)
    {
        rd(x),rd(cost[i]),rd(val[i]);
        C[i]=cost[i];size[i]=1;
        e[i]=(node){i,hd[x]};hd[x]=i;
    }
    
    dfs(1);
    printf("%lld",ans);
    re 0; 
}

 

posted @ 2019-08-14 20:32  凉如水  阅读(145)  评论(0编辑  收藏  举报