zoukankan      html  css  js  c++  java
  • bzoj3672 [Noi2014]购票

    Description

     今年夏天,NOI在SZ市迎来了她30周岁的生日。来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会。
           全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的父亲用道路连接。为了方便起见,我们将全国的 n 个城市用 1 到 n 的整数编号。其中SZ市的编号为 1。对于除SZ市之外的任意一个城市 v,我们给出了它在这棵树上的父亲城市 fv  以及到父亲城市道路的长度 sv
    从城市 v 前往SZ市的方法为:选择城市 v 的一个祖先 a,支付购票的费用,乘坐交通工具到达 a。再选择城市 a 的一个祖先 b,支付费用并到达 b。以此类推,直至到达SZ市。
    对于任意一个城市 v,我们会给出一个交通工具的距离限制 lv。对于城市 v 的祖先 a,只有当它们之间所有道路的总长度不超过 lv  时,从城市 v 才可以通过一次购票到达城市 a,否则不能通过一次购票到达。对于每个城市 v,我们还会给出两个非负整数 pv,qv  作为票价参数。若城市 v 到城市 a 所有道路的总长度为 d,那么从城市 v 到城市 a 购买的票价为 dpv+qv
    每个城市的OIer都希望自己到达SZ市时,用于购票的总资金最少。你的任务就是,告诉每个城市的OIer他们所花的最少资金是多少。

    Input

    第 1 行包含2个非负整数 n,t,分别表示城市的个数和数据类型(其意义将在后面提到)。输入文件的第 2 到 n 行,每行描述一个除SZ之外的城市。其中第 v 行包含 5 个非负整数 f_v,s_v,p_v,q_v,l_v,分别表示城市 v 的父亲城市,它到父亲城市道路的长度,票价的两个参数和距离限制。请注意:输入不包含编号为 1 的SZ市,第 2 行到第 n 行分别描述的是城市 2 到城市 n。

    Output

    输出包含 n-1 行,每行包含一个整数。其中第 v 行表示从城市 v+1 出发,到达SZ市最少的购票费用。同样请注意:输出不包含编号为 1 的SZ市。

    Sample Input

    7 3
    1 2 20 0 3
    1 5 10 100 5
    2 4 10 10 10
    2 9 1 100 10
    3 5 20 100 10
    4 4 20 0 10

    Sample Output


    40
    150
    70
    149
    300
    150

    HINT


    对于所有测试数据,保证 0≤pv≤106,0≤qv≤1012,1≤fv<v;保证 0<sv≤lv≤2×1011,且任意城市到SZ市的总路程长度不超过 2×1011

    输入的 t 表示数据类型,0≤t<4,其中:

    当 t=0 或 2 时,对输入的所有城市 v,都有 fv=v-1,即所有城市构成一个以SZ市为终点的链;

    当 t=0 或 1 时,对输入的所有城市 v,都有 lv=2×1011,即没有移动的距离限制,每个城市都能到达它的所有祖先;

    当 t=3 时,数据没有特殊性质。

    n=2×10^5

    正解:点分治+CDQ分治+斜率优化dp。

    NOIP三合一。。这题首先一看是斜率优化,结果是颗树。。然后我就不会做了,默默地点开题解堕落。。

    如果是在序列上,那么就是斜率优化+CDQ分治搞一下就行了。我们考虑转移到树上该怎么实现。同样,我们可以在树上分治,那么为了保证复杂度,我们采用点分治的方法。当我们找到重心以后,我们可以先递归深度比重心低的那颗子树。然后递归完成后我们就可以求出重心以上所有结点的状态了。然后我们把重心以上的点加入栈中来维护凸线,我们可以倒着加入这样更加方便。然后再将重心的子树的状态全部算出来取最小值就行了。

      1 //It is made by wfj_2048~
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <cstdlib>
      6 #include <cstdio>
      7 #include <vector>
      8 #include <cmath>
      9 #include <queue>
     10 #include <stack>
     11 #include <map>
     12 #include <set>
     13 #define inf (1LL<<60)
     14 #define N (500010)
     15 #define eps 1e-9
     16 #define il inline
     17 #define RG  
     18 #define ll long long
     19 #define calc(i,j) (dp[j]+p[i]*(dis[i]-dis[j])+q[i])
     20 #define getk(i,j) ((double)(dp[i]-dp[j])/(double)(dis[i]-dis[j]))
     21 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     22 
     23 using namespace std;
     24 
     25 struct edge{ ll nt,to,dis; }g[N];
     26 
     27 struct node{ ll id,val; }st[N];
     28 
     29 ll head[N],size[N],fa[N],son[N],dis[N],lim[N],vis[N],que[N],p[N],q[N],dp[N],n,num,cnt;
     30 
     31 il ll gi(){
     32     RG ll x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
     33     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
     34 }
     35 
     36 il ll cmp(const node &a,const node &b){ return a.val>b.val; }
     37 
     38 il void insert(RG ll from,RG ll to,RG ll dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }
     39 
     40 il void dfs(RG ll x){
     41     size[x]=1; RG ll v;
     42     for (RG ll i=head[x];i;i=g[i].nt){
     43     v=g[i].to,dis[v]=dis[x]+g[i].dis;
     44     dfs(v); size[x]+=size[v];
     45     }
     46     return;
     47 }
     48 
     49 il void getroot(RG ll x,RG ll sz,RG ll &rt){
     50     size[x]=1,son[x]=0; RG ll v;
     51     for (RG ll i=head[x];i;i=g[i].nt){
     52     v=g[i].to; if (vis[v]) continue;
     53     getroot(v,sz,rt); size[x]+=size[v];
     54     son[x]=max(son[x],size[v]);
     55     }
     56     son[x]=max(son[x],sz-size[x]);
     57     if (son[rt]>son[x] && size[x]>1) rt=x; return;
     58 }
     59 
     60 il void getlim(RG ll x){
     61     st[++cnt].id=x,st[cnt].val=dis[x]-lim[x];
     62     for (RG ll i=head[x];i;i=g[i].nt)
     63     if (!vis[g[i].to]) getlim(g[i].to);
     64     return;
     65 }
     66 
     67 il void solve(RG ll x,RG ll sz){
     68     if (sz==1) return; RG ll rt=0; getroot(x,sz,rt);
     69     for (RG ll i=head[rt];i;i=g[i].nt) vis[g[i].to]=1;
     70     solve(x,sz-size[rt]+1); cnt=0;
     71     for (RG ll i=head[rt];i;i=g[i].nt) getlim(g[i].to);
     72     sort(st+1,st+cnt+1,cmp); RG ll now=rt,top=0;
     73     for (RG ll i=1;i<=cnt;++i){
     74     while (now!=fa[x] && st[i].val<=dis[now]){
     75         while (top>1 && getk(now,que[top])+eps>=getk(que[top],que[top-1])) top--;
     76         que[++top]=now,now=fa[now];
     77     }
     78     if (top>0){
     79         RG ll l=1,r=top,mid,pos=1;
     80         while (l<=r){
     81         mid=(l+r)>>1; if (mid==top){ pos=top; break; }
     82         if (getk(que[mid],que[mid+1])+eps>=p[st[i].id]) pos=mid+1,l=mid+1; else r=mid-1;
     83         }
     84         dp[st[i].id]=min(dp[st[i].id],calc(st[i].id,que[pos]));
     85     }
     86     }
     87     for (RG ll i=head[rt];i;i=g[i].nt) solve(g[i].to,size[g[i].to]); return;
     88 }
     89 
     90 il void work(){
     91     n=gi(); RG ll d=gi(); for (RG ll i=2;i<=n;++i) fa[i]=gi(),d=gi(),p[i]=gi(),q[i]=gi(),lim[i]=gi(),insert(fa[i],i,d);
     92     for (RG ll i=2;i<=n;++i) dp[i]=inf; son[0]=n+1,dfs(1),solve(1,n);
     93     for (RG ll i=2;i<=n;++i) printf("%lld
    ",dp[i]); return;
     94 }
     95 
     96 int main(){
     97     File("ticket");
     98     work();
     99     return 0;
    100 }
  • 相关阅读:
    vue 前端框架 (二) 表格增加搜索
    vue 前端框架
    数据结构-树的基本操作
    linux的串口驱动分析
    TTY驱动程序架构
    linux MTD系统解析(转)
    DM9000网卡的基本工作原理
    ok6410的LCD裸机范例
    ok6410的DMA裸机总结
    ok6410串口裸机总结
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6416565.html
Copyright © 2011-2022 走看看