• [长链剖分][线段树] Bzoj P1758 重建计划


    Description

    Input

    第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai,Bi,Vi分别表示道路(Ai,Bi),其价值为Vi 其中城市由1..N进行标号

    Output

    输出最大平均估值,保留三位小数

    Sample Input

    4
    2 3
    1 2 1
    1 3 2
    1 4 3

    Sample Output

    2.500

    HINT

    N<=100000,1<=L<=U<=N-1,Vi<=1000000

    题解

    • 我们需要处理出每棵子树中每个深度的dis的最大值,就可以用长链剖分+线段树来维护

    • 先递归长儿子,然后继承长儿子的信息,最后合并短儿子的同时顺便维护答案

    • 我们可以先预处理出长链剖分序,也就是在求dfs序的时候先递归长儿子

    • 这样的话必然满足长儿子的子树的大小必然大于该点为根的树的最大深度,这样我们就可以把深度信息用一棵线段树来储存,那么递归完长儿子后该点就可以直接继承长儿子的答案

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 using namespace std;
     5 const int N=100010;
     6 const double eps=1e-4,inf=1e15;
     7 int n,L,R,cnt,head[N],deep[N],mx[N],son[N],dfn[N],num[N];
     8 double ans,tmp[N],dis[N];
     9 struct tree{int l,r;double mx;}t[N*5];
    10 struct edge{int to,from,w;double v;}e[N*2];
    11 void insert(int x,int y,int v)
    12 {
    13     e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt,e[cnt].w=v;
    14     e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt,e[cnt].w=v;
    15 }
    16 void dfs1(int x,int fa)
    17 {
    18     deep[x]=deep[fa]+1,mx[x]=deep[x];
    19     for (int i=head[x];i;i=e[i].from)
    20         if (e[i].to!=fa) 
    21         {
    22             dfs1(e[i].to,x),mx[x]=max(mx[x],mx[e[i].to]);
    23             if (mx[e[i].to]>mx[son[x]]) son[x]=e[i].to;
    24         }
    25 }
    26 void dfs2(int x,int fa)
    27 {
    28     dfn[x]=++dfn[0];
    29     if (son[x]) dfs2(son[x],x);
    30     for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa&&e[i].to!=son[x]) dfs2(e[i].to,x);
    31 }
    32 void build(int d,int l,int r)
    33 {
    34     t[d].mx=-inf;
    35     if (l==r) { num[l]=d; return; }
    36     int mid=l+r>>1;
    37     build(d*2,l,mid),build(d*2+1,mid+1,r);
    38 }
    39 void modify(int d,int l,int r,int x,double y)
    40 {
    41     if (l==r) { t[d].mx=max(t[d].mx,y); return; }
    42     int mid=l+r>>1;
    43     if (x<=mid) modify(d*2,l,mid,x,y); else modify(d*2+1,mid+1,r,x,y);
    44     t[d].mx=max(t[d*2].mx,t[d*2+1].mx);
    45 }
    46 double query(int d,int l,int r,int x,int y)
    47 {
    48     if (x>y) return -inf;
    49     if (l==x&&r==y) return t[d].mx;
    50     int mid=l+r>>1;
    51     return max(query(d*2,l,mid,x,min(y,mid)),query(d*2+1,mid+1,r,max(x,mid+1),y));
    52 }
    53 void dfs(int x,int fa)
    54 {
    55     modify(1,1,n,dfn[x],dis[x]);
    56     for (int i=head[x];i;i=e[i].from) if (e[i].to==son[x]) dis[e[i].to]=dis[x]+e[i].v,dfs(e[i].to,x);
    57     for (int i=head[x];i;i=e[i].from)
    58         if (e[i].to!=fa&&e[i].to!=son[x])
    59         {
    60             dis[e[i].to]=dis[x]+e[i].v,dfs(e[i].to,x);
    61             for (int j=1;j<=mx[e[i].to]-deep[x];j++)
    62             {
    63                 tmp[j]=t[num[dfn[e[i].to]+j-1]].mx;
    64                 if (j<=R) ans=max(ans,query(1,1,n,max(1,dfn[x]+L-j),min(dfn[x]+mx[x]-deep[x],dfn[x]+R-j))+tmp[j]-2*dis[x]);
    65             }
    66             for (int j=1;j<=mx[e[i].to]-deep[x];j++) modify(1,1,n,dfn[x]+j,tmp[j]);
    67         }
    68     ans=max(ans,query(1,1,n,dfn[x]+L,min(dfn[x]+mx[x]-deep[x],dfn[x]+R))-dis[x]);
    69 }
    70 int main()
    71 {
    72     scanf("%d%d%d",&n,&L,&R);
    73     for (int i=1,x,y,z;i<n;i++) scanf("%d%d%d",&x,&y,&z),insert(x,y,z);
    74     dfs1(1,0),dfs2(1,0);
    75     double l=0,r=1000000; t[0].mx=-inf;
    76     while (r-l>eps)
    77     {
    78         double mid=(l+r)/2;
    79         for (int i=1;i<=cnt;i++) e[i].v=e[i].w-mid;
    80         ans=-inf,dis[1]=0,build(1,1,n),dfs(1,0);
    81         if (ans<=0) r=mid; else l=mid;
    82     }
    83     printf("%.3lf",l);
    84 }
  • 相关阅读:
    python随笔:邮箱题目
    05 小程序自定义组件
    04 小程序常用组件-view text rich-text icon swiger
    03 小程序语法-WXSS样式-尺寸-样式 -选择器
    02 小程序语法-数据绑定与事件绑定
    01 小程序入门与vscode开发加装插件
    JAVA25-Git、Vue.js
    JAVA14-File类、递归、字节流、字符流、缓冲流、转换流、序列化流、Files
    JAVA13-异常、线程、同步、等待与唤醒案例、线程池、Lambda表达式
    JAVA12-Scanner类、Random类、ArrayList类、String类、static、Arrays类、Math类、静态方法
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11192732.html
Copyright © 2020-2023  润新知