天天看點

dispatching HYSBZ - 2809

https://www.lydsy.com/JudgeOnline/problem.php?id=2809

先求樹圖的dfs序 對dfs序列從前到後建立靜态主席樹 維護對應工資區間上有多少人

枚舉每個點 找到以該點為根的子樹對應的區間 字首和做差得到一棵線段樹 區間二分查詢 先看左子樹工資上夠不夠 夠就把人都算上再查右樹 不夠就從左樹再遞歸

還有要注意的是 離散化後不能去重 因為需要求人數 如果離散化後再建樹 會把很多人算在同一工資水準 這樣邊界處理會很惡心

#include <bits/stdc++.h>
using namespace std;
#define ll long long

struct node0
{
    int id;
    ll val;
};

struct node1
{
    int v;
    int next;
};

struct node2
{
    int l;
    int r;
    ll val;
    int cnt;
};

node0 tmp[100010];
node1 edge[100010];
node2 tree[2000010];
ll cval[100010],lval[100010];
int first[100010],pos[100010],root[100010],fa[100010],mp1[100010],mp2[100010],sum[100010];
ll tot;
int n,num;

bool cmp(node0 n1,node0 n2)
{
    return n1.val<n2.val;
}

ll getmax(ll a,ll b)
{
    if(a>b) return a;
    else return b;
}

void addedge(int u,int v)
{
    edge[num].v=v;
    edge[num].next=first[u];
    first[u]=num++;
}

void dfs(int cur)
{
    int i,v;
    num++;
    mp1[cur]=num,mp2[num]=cur,sum[cur]=1;
    for(i=first[cur];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        dfs(v);
        sum[cur]+=sum[v];
    }
}

int build(int l,int r)
{
    int cur,m;
    cur=num++;
    tree[cur].l=0,tree[cur].r=0,tree[cur].val=0,tree[cur].cnt=0;
    if(l==r) return cur;
    m=(l+r)/2;
    tree[cur].l=build(l,m);
    tree[cur].r=build(m+1,r);
    return cur;
}

int update(int rot,int tar,ll val,int l,int r)
{
    int cur,m;
    cur=num++;
    tree[cur]=tree[rot];
    tree[cur].val+=val;
    tree[cur].cnt++;
    if(l==r) return cur;
    m=(l+r)/2;
    if(tar<=m) tree[cur].l=update(tree[rot].l,tar,val,l,m);
    else tree[cur].r=update(tree[rot].r,tar,val,m+1,r);
    return cur;
}

void init()
{
    int i;
    num=0;
    root[0]=build(1,n);
    for(i=1;i<=n;i++)
    {
        root[i]=update(root[i-1],pos[mp2[i]],cval[mp2[i]],1,n);
    }
}

int query(int lrot,int rrot,ll val,int l,int r)
{
    ll res;
    int m;
    if(l==r)
    {
        if(val>=tree[rrot].val-tree[lrot].val) return tree[rrot].cnt-tree[lrot].cnt;
        else return 0;
    }
    res=tree[tree[rrot].l].val-tree[tree[lrot].l].val,m=(l+r)/2;
    if(val<=res) return query(tree[lrot].l,tree[rrot].l,val,l,m);
    else return tree[tree[rrot].l].cnt-tree[tree[lrot].l].cnt+query(tree[lrot].r,tree[rrot].r,val-res,m+1,r);
}

ll solve()
{
    ll res,cnt;
    int i,pl,pr,p;
    res=0;
    for(i=1;i<=n;i++)
    {
        pl=mp1[i],pr=mp1[i]+sum[i]-1;
        cnt=query(root[pl-1],root[pr],tot,1,n);
        res=getmax(res,cnt*lval[i]);
    }
    return res;
}

int main()
{
    int i;
    while(scanf("%d%lld",&n,&tot)!=EOF)
    {
        memset(first,-1,sizeof(first));
        num=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d%lld%lld",&fa[i],&cval[i],&lval[i]);
            tmp[i].id=i,tmp[i].val=cval[i];
            if(i>1) addedge(fa[i],i);
        }
        sort(tmp+1,tmp+n+1,cmp);
        for(i=1;i<=n;i++) pos[tmp[i].id]=i;
        num=0;
        dfs(1);
        init();
        printf("%lld\n",solve());
    }
    return 0;
}