[Apio2012] dispatching (dispatch) - segment tree merge

Face questions

  Bzoj2809

Resolve

  According to greedy strategy we want to choose as many people, so people will choose less cost, then for each node can build a range tree line, the father of the tree line and then a single point of all of his son's tree line consolidation modified from, so you can quickly check how many number to meet the requirements, the number and the cost of maintaining the tree line and, taking into account the range have 1e9, while the number only 1e5, we consider discrete, since each node has a correspondence the tree line, so we opened the dynamic point to compress space. The question then is how to merge the tree line, we want to set up a node number y merged into x number of nodes were considered about his son, if x son had left, then down recursive, if a node number y no son left return, or if it reaches L == R, merger information; if x and y have not left son, the left son y then directly assigned to the node number of the left son of x, returns. Right Son of operation is the same.

  There is also a small optimization when combining the tree line, if his son left the sum has been greater than m, and update information on the parent node, not with a right son, returned directly, like really quickly.

  See the rest of the details of the code.

 Code:

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100005;

template<class T> void read(T &re)
{
    re=0;
    T sign=1;
    char tmp;
    while((tmp=getchar())&&(tmp<'0'||tmp>'9')) if(tmp=='-') sign=-1;
    re=tmp-'0';
    while((tmp=getchar())&&(tmp>='0'&&tmp<='9')) re=(re<<3)+(re<<1)+(tmp-'0');
    re*=sign;
}

int tot, root[maxn], n, m, w[maxn], v[maxn], mas, aw[maxn], cnt, f[maxn];
ll ans;

struct seg_tree{
    int ls, rs, num;
    ll sum;
}tr[maxn * 20];

void update(int x)
{
    tr[x].num = tr[tr[x].ls].num + tr[tr[x].rs].num ;
    tr[x].sum = tr[tr[x].ls].sum + tr[tr[x].rs].sum ;
}

void Merge(int x, int y, int L, int R)
{
    if(!y)    return ;
    if(L == R)
    {
        tr[x].num += tr[y].num;
        tr[x].sum += tr[y].sum;
        return ;
    }
    int mid = (L + R)>>1;
    if(tr[x].ls)
        Merge(tr[x].ls, tr[y].ls, L, mid);
    else
        tr[x].ls = tr[y].ls;
    if(tr[tr[x].ls].sum > m)
    {
        update(x);
        return ;
    }    
    if(tr[x].rs)
        Merge(tr[x].rs, tr[y].rs, mid + 1, R);
    else
        tr[x].rs = tr[y].rs;
    update(x);
}

void Modify(int x, int val, int L, int R)
{
    if(L == R)
    {
        tr[x].num ++;
        tr[x].sum += aw[val];
        return ;
    }
    int mid = (L + R)>>1;
    if(val <= mid)
    {
        if(!tr[x].ls)
            tr[x].ls = ++tot;
        Modify(tr[x].ls, val, L, mid);
    }
    else
    {
        if(!tr[x].rs)
            tr[x].rs = ++tot;
        Modify(tr[x].rs, val, mid + 1, R);
    }
    update(x);
}

int Query(int x, int L, int R, ll rest)
{
    if(rest >= tr[x].sum)
        return tr[x].num;
    if(L == R)
        return rest / aw[L];
    int mid = (L + R)>>1, ret = 0;
    if(tr[x].ls && rest <= tr[tr[x].ls].sum)
        ret += Query(tr[x].ls, L, mid, rest);
    else if(tr[x].rs)
    {
        ret += tr[tr[x].ls].num ;
        ret += Query(tr[x].rs, mid + 1, R, rest - tr[tr[x].ls].sum);
    }    
    return ret;
}

int main()
{
    read(n);read(m);
    for(int i = 1; i <= n; ++i)
    {
        root[i] = ++tot;
        int x, y, z;
        read(x);read(y);read(z);
        f[i] = x;
        aw[i] = w[i] = y;
        v[i] = z;
    }
    sort(aw + 1, aw + n + 1);
    cnt = unique(aw + 1, aw + n + 1) - aw - 1;
    for(int i = n; i; --i)
    {
        Modify(root[i], lower_bound(aw + 1, aw + cnt + 1, w[i]) - aw, 1, cnt);
        ans = max(ans, 1LL * v[i] * Query(root[i], 1, cnt, (ll)m));
        if(f[i])
            Merge(root[f[i]], root[i], 1, cnt);
    }
    printf("%lld", ans);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/Joker-Yza/p/11235656.html