hdu 5956 The Elder

Posted 日拱一卒 功不唐捐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 5956 The Elder相关的知识,希望对你有一定的参考价值。

http://acm.hdu.edu.cn/showproblem.php?pid=5956

 

转移方程:dp[i]=(dis[i]-dis[j])*(dis[i]-dis[j])+P+dp[j]

斜率优化,可持久化单调队列维护

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 100001

typedef long long LL;

int P;

int front[N],to[N<<1],nxt[N<<1],val[N<<1],tot;

int dis[N];

int head,tail,q[N];
LL dp[N];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-0; c=getchar(); }
}

void add(int u,int v,int w)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; val[tot]=w;
}

inline double X(int i,int j) { return dis[j]-dis[i]; }
inline double Y(int i,int j) { return 1LL*dis[j]*dis[j]+dp[j]-1LL*dis[i]*dis[i]-dp[i]; }

void dfs(int x,int y)
{
    int now_h=head,now_t=tail;
    int l=head,r=tail-2,mid,tmp=-1;
    while(l<=r)
    {
        mid=l+r>>1;
        if(Y(q[mid],q[mid+1])>=2*dis[x]*X(q[mid],q[mid+1])) tmp=mid,r=mid-1;
        else l=mid+1;
    }
    if(tmp!=-1) head=tmp;
    else head=tail-1;
    int j=q[head];
    dp[x]=1LL*(dis[x]-dis[j])*(dis[x]-dis[j])+P+dp[j];
    l=head,r=tail-2,tmp=-1;
    while(l<=r)
    {
        mid=l+r>>1;
        if(Y(q[mid],q[mid+1])*X(q[mid+1],x)<=Y(q[mid+1],x)*X(q[mid],q[mid+1])) tmp=mid,l=mid+1;
        else r=mid-1;
    }
    if(tmp!=-1) tail=tmp+2;
    else tail=head+1;
    int rr=q[tail];
    q[tail++]=x;
    for(int i=front[x];i;i=nxt[i])
        if(to[i]!=y)
        {
            dis[to[i]]=dis[x]+val[i];
            dfs(to[i],x);
        }
    head=now_h; q[tail-1]=rr; tail=now_t;
}


void clear()
{
    tot=0;
    memset(front,0,sizeof(front));
}

int main()
{
    int T;
    read(T);
    int n,u,v,w;
    while(T--)
    {
        clear();
        read(n); read(P);
        for(int i=1;i<n;++i)
        {
            read(u); read(v); read(w);
            add(u,v,w);
        }
        dp[1]=-P;
        for(int i=front[1];i;i=nxt[i])
        {
            head=0; tail=1;
            q[0]=1;
            dis[to[i]]=val[i];
            dfs(to[i],1);
        }
        LL ans=0;
        for(int i=2;i<=n;++i) ans=max(ans,dp[i]);
        cout<<ans<<\n;
    }
}

 

以上是关于hdu 5956 The Elder的主要内容,如果未能解决你的问题,请参考以下文章

[HDU5956]The Elder

hdu 5956 The Elder 2016ACM/ICPC沈阳赛区现场赛I

HDU 5956 The Elder (树上斜率DP)

HDU - 59562016ACM/ICPC亚洲区沈阳站I - The Elder 树上斜率优化dp

HDU4057 Rescue the Rabbit(AC自动机+状压DP)

算法5956. 找出数组中的第一个回文字符串(java / c / c++ / python / go / rust)