码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-08-18 09:18:17      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:for   推出   can   one   nbsp   include   music   一个个   mes   

之前学斜率优化的锅,凸包没学会,当时是不等式搞过去的,考试时妄想推出和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\n",zui[i]);
58 }
View Code

 

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

标签:for   推出   can   one   nbsp   include   music   一个个   mes   

原文地址:https://www.cnblogs.com/2018hzoicyf/p/11371304.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!