zoukankan      html  css  js  c++  java
  • #1992. 购票(ticket)

    题目描述

    题解

    考虑啥限制都没有的话,也就是在一个序列上且没有 $l$ 的限制,那就是 $dp$ 然后斜率优化

    $f_i$ 表示 $i$ 的答案, $f_i=min(f_j+(d_i-d_j)p_i+q_i)$ ,其中 $d_i$ 表示 $s$ 的前缀和,可以化成斜率优化的式子

    由于斜率不递增所以在凸包上二分即可

    考虑 $l$ 的限制的话,那我们可以做类似 $cdq$ 的东西,也就是考虑 $[l,mid]$ 对 $[mid+1,r]$ 的影响,那可以对右区间以最前能取到的点从大到小排序,然后双指针加入凸包即可

    考虑在一棵树上的话,那我们考虑点分治,即对于树 $u$ 求出了重心 $rt$ ,考虑 $(u,rt)$ 路径上的点对 $rt$ 子树的影响,那我们可以先除去 $rt$ 子树内的点(除了 $rt$ ),然后递归求出剩下点的 $dp$ 值,然后我们可以像刚刚的操作即把 $rt$ 子树内除了 $rt$ 的点按照最高能取到的点按深度从大到小排序,然后双指针加入凸包即可

    效率: $O(nlog^2n)$

    代码

    #include <bits/stdc++.h>
    #define LL long long
    #define db long double
    using namespace std;
    const int N=2e5+5;
    int n,fa[N],o,rt,sz[N],son[N],a[N],hd[N],V[N],nx[N],t,S[N],tp;
    LL d[N],s[N],p[N],q[N],g[N],f[N];bool vis[N];
    bool cmp(int A,int B){
        return d[A]-g[A]>d[B]-g[B];
    }
    void add(int u,int v){
        nx[++t]=hd[u];V[hd[u]=t]=v;
    }
    db K(int x,int y){
        return ((db)f[y]-f[x])/((db)d[y]-d[x]);
    }
    void Dis(int x){
        for (int i=hd[x];i;i=nx[i])
            d[V[i]]=d[x]+s[V[i]],Dis(V[i]);
    }
    void Sz(int x){
        sz[x]=1;
        for (int i=hd[x],v;i;i=nx[i])
            if (!vis[v=V[i]])
                Sz(v),sz[x]+=sz[v];
    }
    void Rt(int x){
        son[x]=o-sz[x];
        for (int i=hd[x],v;i;i=nx[i])
            if (!vis[v=V[i]])
                Rt(v),son[x]=max(son[x],sz[v]);
        if (son[x]<=son[rt]) rt=x;
    }
    void find(int x){
        a[++t]=x;
        for (int i=hd[x];i;i=nx[i])
            if (!vis[V[i]]) find(V[i]);
    }
    void work(int x){
        Sz(x);o=sz[x];rt=0;Rt(x);
        if (o==1){vis[x]=1;return;}
        for (int i=hd[rt];i;i=nx[i]) vis[V[i]]=1;
        int u=rt;work(x);tp=t=0;
        for (int i=hd[u];i;i=nx[i])
            vis[V[i]]=0,find(V[i]);
        sort(a+1,a+t+1,cmp);int X=x;x=u;
        for (int i=1,v,l,r,j;i<=t;i++){
            v=a[i];
            while(d[u]>=d[X] && d[u]>=d[v]-g[v]){
                while(tp>1 && K(S[tp-1],u)>=K(S[tp-1],S[tp])) tp--;
                S[++tp]=u;u=fa[u];
            }
            if (!tp) continue;l=1;r=tp;
            while(l<r){
                j=(l+r+1)>>1;
                if (K(S[j],S[j-1])>=p[v]) l=j;
                else r=j-1;
            }
            f[v]=min(f[v],f[S[l]]+(d[v]-d[S[l]])*p[v]+q[v]);
        }
        vis[x]=1;
        for (int i=hd[x];i;i=nx[i]) work(V[i]);
    }
    int main(){
        cin>>n>>tp;son[0]=1e9;d[0]=-1;
        for (int i=2;i<=n;i++)
            scanf("%d%lld%lld%lld%lld",
            &fa[i],&s[i],&p[i],&q[i],&g[i]),
            f[i]=2e18,add(fa[i],i);
        Dis(1);work(1);
        for (int i=2;i<=n;i++)
            printf("%lld
    ",f[i]);
        return 0;
    }
  • 相关阅读:
    LPTHW 笨办法学python 20章
    LPTHW 笨方法学python 19章
    LPTHW 笨方法学python 18章
    LPTHW 笨方法学习python 16章
    hadoop删除节点。
    url中的百分号转译
    thrift编译安装
    python学习:函数的学习
    jsp静态导入和动态导入 笔记
    简要描述cookie和session的区别:
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12288854.html
Copyright © 2011-2022 走看看