[Convex Hull Maintenance - Parallel Stacking] LGP3642 [APIO2016] Fireworks Show

[Title]
The original title is the
main idea of ​​the title: I will give you a rooted tree with edge weights. You can arbitrarily modify the edge weights of the tree. Ask what is the least modified sum of the edge weights, which can make the distance from the root node to all leaf nodes. same.

[Title analysis]
After violent thinking, it is found that it is a convex hull merger or the like, but this merger is very intriguing.

[Problem-solving ideas]
APIO's questions are really wonderful!

First, we set f(i,x) as the minimum cost of point i when the depth of all its leaf nodes is x,
we can find that this is a downward convex function, and it is once, and the slope of the adjacent ends changes to 1.
Obviously the optimum is taken when the slope is 0, so for each point all we actually do is merge the convex hulls of all its children.
The interval to take the minimum value is [ L , R ] , and then we have the following.

H ( x ) = { H ( x ) + w x L H ( L ) + w ( x L ) L x L + w H ( L ) L + w x R + w H ( L ) + ( x R ) w R + w x

After thinking about this for a long time, I personally found that it is impossible to do it, because there will be a lot of nodes when a bunch of points are inserted.
Then sc tells me that the splay merge is log^2, and the heuristic merge is also log^2, but the splay of the heuristic merge order is log.
It felt extremely difficult to fight, the sc boss bravely started to fight, and I was still thinking.

The next day I was studying the properties of this convex hull again, thinking about whether it is possible to maintain the convex hull with a simple data structure.
Seeing that the merged convex hull above actually only changes the convex hull to the left of the optimum, so the convex hull to the right of the optimum is useless.
It is also found that in fact, we do not need to know the actual shape of the convex hull. We only need to remember the position of each vertex, and we can know the entire function.
Then the question is how to maintain these breakpoint positions.
We found that when we merged the convex hull, we must merge the two convex hulls with the slope of 0 at the extreme right. The merging of the two convex hulls is actually equivalent to translating one convex hull to the left, and then the slope is 0. Three segments of -1,0,1 are inserted into the convex hull.
What happens after inserting it? We find that the slope on the far right of the convex hull is at most 1. Then the convex hull of all the child nodes of a node is combined, and the rightmost slope of its convex hull is at most (the number of child nodes),
so we can simply use a heap to maintain the vertices of the convex hull!
Simply put, it is to merge all the convex hulls to the parent node, pop up the node on the right (the number of child nodes), and then add two more nodes to the parent node.

Finally, take out all the points on all 1 nodes, and then subtract them in turn.

wxh:
f ( 0 ) = The weight of the tree edge, and then the slope is -1 until 0 each time, then
it can be reduced from right to left
s u m = p [ i ] can be understood as p [ i ] The contribution of the slope = -1 is taken into account, and then the slope of all previous lines - = 1

【Reference Code】

#include<bits/stdc++.h>
#define mkp(x,y) make_pair(x,y)
using namespace std;

typedef long long LL;
typedef long double ldb;
typedef pair<int,int> pii;
const int N=6e5+10;

int n,m,cnt,tot;
int fa[N],len[N],rt[N],du[N];
LL sum,p[N]; 

LL read()
{
    LL ret=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=0;c=getchar();}
    while(isdigit(c)){ret=(ret<<1ll)+(ret<<3ll)+(c^48);c=getchar();}
    return f?ret:-ret;
}

struct Tnode
{
    int l,r,dis;
    LL val;
};
Tnode q[N];

int merge(int x,int y)
{
    if(!x || !y) 
        return x+y;
    if(q[x].val<q[y].val) 
        swap(x,y);
    q[x].r=merge(q[x].r,y);
    if(q[q[x].l].dis<q[q[x].r].dis)
        swap(q[x].l,q[x].r);
    q[x].dis=(q[x].r?q[q[x].r].dis+1:0);
    return x;
} 

int pop(int x)
{
    return merge(q[x].l,q[x].r);
}

int main()
{
    freopen("LGP3642.in","r",stdin);
    freopen("LGP3642.out","w",stdout);

    n=read();m=read();
    for(int i=2;i<=n+m;++i)
    {
        fa[i]=read();len[i]=read();
        sum+=len[i];du[fa[i]]++;
    }

    for(int i=n+m;i>1;--i)
    {
        LL l=0,r=0;
        if(i<=n)
        {
            while(--du[i])
                rt[i]=pop(rt[i]);
            l=q[rt[i]].val;rt[i]=pop(rt[i]); 
            r=q[rt[i]].val;rt[i]=pop(rt[i]);
        }
        q[++tot].val=l+len[i];q[++tot].val=r+len[i];
        rt[i]=merge(rt[i],merge(tot,tot-1));
        rt[fa[i]]=merge(rt[fa[i]],rt[i]);   
    }

    while(du[1]--)
        rt[1]=pop(rt[1]);
    while(rt[1])
        p[++cnt]=q[rt[1]].val,rt[1]=pop(rt[1]);
    for(int i=1;i<=cnt;++i) 
        sum-=p[i];
    printf("%lld\n",sum); 

    return 0;
} 

[Summary]
I was also bored when I was thinking in the middle.
this story tells usThe data structure is too toxicThink more.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325389997&siteId=291194637