bzoj2809: [Apio2012]dispatching

来源:互联网 发布:win10端口设置在哪里 编辑:程序博客网 时间:2024/06/08 11:37

练习一下启发式合并,就照着别人写了一遍。(好菜QAQ)
从后往前枚举管理者,贪心选择最便宜的忍者,用splay+启发式合并维护。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int read(){    char ch=getchar();int f=0;    while(ch<'0'||ch>'9') ch=getchar();    while(ch>='0'&&ch<='9') {f=f*10+(ch^48);ch=getchar();}    return f;}long long sum[1000005],l[1000005],mx,ans;int root[1000005],fa[1000005],ch[1000005][2],w[1000005],v[1000005],b[1000005],size[1000005];int n,cnt;void pushup(int x){    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;    sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+v[w[x]];}void rotate(int x,int &f){    int y=fa[x],z=fa[y],l,r;    l=(ch[y][1]==x);r=l^1;    if(z) ch[z][ch[z][1]==y]=x;    ch[y][l]=ch[x][r];ch[x][r]=y;    fa[ch[y][l]]=y;fa[y]=x;fa[x]=z;    pushup(y);pushup(x);    if(y==f) f=x;}void splay(int x,int &f){    while(x!=f)    {        int y=fa[x],z=fa[y];        if(y!=f)        {            if(ch[y][0]==x^ch[z][0]==y) rotate(x,f);else rotate(y,f);        }        rotate(x,f);    }}void insert(int &x,int f,int p,int k){    if(!x)    {        w[x=++cnt]=p;        fa[x]=f;        size[x]=1;        sum[x]=v[p];        splay(x,root[k]);        return ;    }    insert(ch[x][v[p]>v[w[x]]],x,p,k);}int find(int x,long long mx){    if(!x) return 0;    if(mx<sum[ch[x][0]]) return find(ch[x][0],mx);    int ans=size[ch[x][0]];    mx-=sum[ch[x][0]];    if(mx<v[w[x]]) return ans;    ans++,mx-=v[w[x]];    return ans+find(ch[x][1],mx);}void dfs(int x,int f){    if(!x) return;    insert(root[f],0,w[x],f);    dfs(ch[x][0],f);    dfs(ch[x][1],f);}void merge(int x,int y){    if(size[root[x]]<size[root[y]]) swap(root[x],root[y]);    dfs(root[y],x);}int main(){    n=read(),mx=read();    for(int i=1;i<=n;i++)    {        b[i]=read(),v[i]=read(),l[i]=read(),insert(root[i],0,i,i);    }    for(int i=n;i;i--)    {        int x=find(root[i],mx);        ans=max(ans,(long long)x*l[i]);        if(i!=1) merge(b[i],i);    }    cout<<ans;    return 0;}