BZOJ 2809 [Apio2012]dispatching

题解:

可并大根对维护即可

注意long long

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=200009;

int n,m;
int abl[maxn];
long long ans=0;

int fa[maxn],ch[maxn][2],dis[maxn];
long long sum[maxn];
int siz[maxn],ky[maxn];
int Mer(int x,int y){
    if((x==0)||(y==0))return x+y;
    
    if(ky[x]<ky[y])swap(x,y);
    ch[x][1]=Mer(ch[x][1],y);
    sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+ky[x];
    siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    if(dis[ch[x][1]]>dis[ch[x][0]])swap(ch[x][0],ch[x][1]);
    dis[x]=dis[ch[x][1]]+1;
    return x;
}

int root;

int cntedge=0;
int head[maxn]={0};
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
    nex[++cntedge]=head[x];
    to[cntedge]=y;
    head[x]=cntedge;
}

int Dp(int x){
    int rt=x;
    for(int i=head[x];i;i=nex[i]){
        rt=Mer(rt,Dp(to[i]));
    }
    while(sum[rt]>m){
        fa[ch[rt][0]]=0;
        fa[ch[rt][1]]=0;
        rt=Mer(ch[rt][0],ch[rt][1]);
    }
    ans=max(ans,1LL*abl[x]*siz[rt]);
    return rt;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i){
        int x;scanf("%d",&x);
        if(x==0)root=i;
        else Addedge(x,i);
        scanf("%d%d",&ky[i],&abl[i]);
        siz[i]=1;sum[i]=ky[i];
    }
    
    Dp(root);
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2018-03-25 23:37  ws_zzy  阅读(119)  评论(0编辑  收藏  举报