• #Lost My Music 凸包+链表倍增优化 <凉宫春日的忧郁>


    之前学斜率优化的锅,凸包没学会,当时是不等式搞过去的,考试时妄想推出和u无关,只和祖先有关的不等式,失败。。。

    先看式子(c[fa]-c[son])/(dep[son]-dep[fa]),看起来很别扭,尝试加负号,就变成了斜率(我们以dep为x轴,dep为y轴建坐标系),要求斜率最大,为下凸包,

    这是模拟一个点尝试进栈,两条橙线都不能维护成凸包,要出栈,绿线刚好可以,连绿线前的点也可以,不过并没有这条绿线优

    kx地开栈?不太妙,如果是序列问题那是没问题,但树上问题,没下到一个子节点就会失去此节点应有信息,进而影响到其他子节点,所以考虑用链表,然而不太像前向星那种nt的链表,开个数组记录此点在栈中的上一个点是谁就可以了(可以说是pre)。

    然后是T80的好成绩,考虑优化,这玩意很像一个fat数组,我们一个个找一定很慢的,要优化成跳一大段,想到树上倍增嘛,我们可以像树上倍增祖先一样,倍增此点多少辈pre

    keycode:

        sd[u]=sd[fa]+1;
        lian[u][0]=fa;
        int a,b;
        for(reg int j=lim;j>=0;--j)
            while(1){
                a=lian[lian[u][0]][j];
                if(!a)break;
                b=lian[a][0];
                if(!b)break;
                if(cal(a,b)<cal(a,u))break;
                lian[u][0]=b;
            }
        //cout<<u<<" "<<lian[u][0]<<endl;
        while(1){
            a=lian[u][0];
            if(!a)break;
            b=lian[a][0];
            if(!b)break;
            if(cal(a,b)<cal(a,u))break;
            lian[u][0]=b;
        }
        zui[u]=-1.0*cal(lian[u][0],u);
        for(reg int j=1;j<=lim;++j)
            lian[u][j]=lian[lian[u][j-1]][j-1];
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #define reg register 
     5 using namespace std;
     6 const int MAXN=500010;
     7 int n;
     8 double c[MAXN],sd[MAXN];
     9 struct rr{
    10     int nt,to;
    11 }bl[MAXN];int hd[MAXN],itot;
    12 void add(int x,int y){
    13     bl[++itot].to=y;
    14     bl[itot].nt=hd[x];
    15     hd[x]=itot;
    16 }
    17 inline double cal(int s,int f){return (c[s]-c[f])/(sd[s]-sd[f]); }
    18 int lian[MAXN][25];
    19 double zui[MAXN];
    20 int lim;
    21 void dfs(int u,int fa){
    22     sd[u]=sd[fa]+1;
    23     lian[u][0]=fa;
    24     int a,b;
    25     for(reg int j=lim;j>=0;--j)
    26         while(1){
    27             a=lian[lian[u][0]][j];
    28             if(!a)break;
    29             b=lian[a][0];
    30             if(!b)break;
    31             if(cal(a,b)<cal(a,u))break;
    32             lian[u][0]=b;
    33         }
    34     //cout<<u<<" "<<lian[u][0]<<endl;
    35     while(1){
    36         a=lian[u][0];
    37         if(!a)break;
    38         b=lian[a][0];
    39         if(!b)break;
    40         if(cal(a,b)<cal(a,u))break;
    41         lian[u][0]=b;
    42     }
    43     zui[u]=-1.0*cal(lian[u][0],u);
    44     for(reg int j=1;j<=lim;++j)
    45         lian[u][j]=lian[lian[u][j-1]][j-1];
    46     for(reg int i=hd[u];i;i=bl[i].nt)
    47         dfs(bl[i].to,u);
    48 }
    49 int main(){
    50     //freopen("da.in","r",stdin);
    51     //freopen("hh.out","w",stdout);
    52     scanf("%d",&n);
    53     lim=log2(n)+1;
    54     for(reg int i=1;i<=n;++i)scanf("%lf",&c[i]);
    55     for(reg int i=2,a;i<=n;++i)scanf("%d",&a),add(a,i);
    56     dfs(1,0);
    57     for(reg int i=2;i<=n;++i)printf("%.6lf
    ",zui[i]);
    58 }
    View Code

     

  • 相关阅读:
    《JavaScript DOM 编程艺术》读书笔记
    《精通CSS:高级Web标准解决方案》读书笔记
    计算机专业考研复试面试数据结构
    单元测试框架NUnit 之 Extensibility 例子
    单元测试框架NUnit 之 Extensibility可扩展性
    你应该知道的 asp.net webform之异步页面
    viewstate 应该注意的
    必须要知道的session
    javascript应该注意的小case数据类型
    单元测试框架NUnit 之 Attributes特性(二)
  • 原文地址:https://www.cnblogs.com/2018hzoicyf/p/11371304.html
Copyright © 2020-2023  润新知