[BZOJ2809][Apio2012]dispatching (dfs preface + chairman tree)

Title:

I'm a hyperlink

Explanation:

Obviously, for each ninja, we can only select the nodes in its subtree. The smaller the salary of these nodes, the better. So our direct idea is to maintain the weight and the number of ninjas in the subtree < = m. It seems that we can use dfs order + chairman tree to maintain them?

It seems that it's not easy to bind a subtree to a vertex. Let's transform it: discard the previous vertices and only build the tree in dfs order, so that although you will bind the leaf nodes globally, you can bind them in[i]-1 and out[i] when you query

Note that the line segment tree is built according to the weight, but each node must have an interval, and one node cannot have two ninjas. Although you can multiply them, you cannot deal with the situation that only one ninjas is selected

This requires us to score the same size when we are discrete, so STL will not work. We need to use the original array method
p[i] represents the subscript in a of ranking I, so b is our discrete array

code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#define LL long long 
using namespace std;
const int N=100005;
int tot,nxt[N*2],point[N],v[N*2],in[N],out[N],dfn[N],sz,root[N],nn,c[N],b[N],p[N];
struct hh{int l,r,w;LL sum;}t[N*20];LL ans,l[N],m;
int cmp(int x,int y){return c[x]<c[y];}
void addline(int x,int y)
{
    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void dfs(int x,int fa)
{
    in[x]=++nn; dfn[nn]=x;
    for (int i=point[x];i;i=nxt[i])
      if (v[i]!=fa) dfs(v[i],x);
    out[x]=nn;
}
void insert(int &now,int l,int r,int x,LL v)
{
    t[++sz]=t[now]; now=sz;
    t[now].w++; t[now].sum+=v;
    if (l==r) return;
    int mid=(l+r)>>1;
    if (x<=mid) insert(t[now].l,l,mid,x,v);
    else insert(t[now].r,mid+1,r,x,v);
}
int qurry(int x,int y,int l,int r,LL m)
{
    if (l==r)
    {
        if (t[y].sum-t[x].sum<=m) return t[y].w-t[x].w;
        else return 0;
    }
    int mid=(l+r)>>1;LL sum=t[t[y].l].sum-t[t[x].l].sum;
    if (sum<=m) return t[t[y].l].w-t[t[x].l].w+qurry(t[x].r,t[y].r,mid+1,r,m-sum);
    else return qurry(t[x].l,t[y].l,l,mid,m);
}
int main()
{
    int n,x,s=0,gen;
    scanf("%d%lld",&n,&m);
    for (int i=1;i<=n;i++)
    {
        p[i]=i;
        scanf("%d%d%lld",&x,&c[i],&l[i]);
        if (x==0) gen=i;
        else addline(i,x);
    }
    sort(p+1,p+n+1,cmp);//Subscript in a with p[i] ranking I 
    for (int i=1;i<=n;i++) b[p[i]]=i;//Discrete array 
    dfs(gen,0);
    for (int i=1;i<=n;i++)
    {
        root[i]=root[i-1];
        insert(root[i],1,n,b[dfn[i]],c[dfn[i]]);
    }
    for (int i=1;i<=n;i++)
    {
        LL aa=qurry(root[in[i]-1],root[out[i]],1,n,m);
        ans=max(ans,l[i]*aa);
    }
    printf("%lld",ans);
}

Posted by The Eagle on Thu, 07 May 2020 08:59:53 -0700