标签: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 }
#Lost My Music 凸包+链表倍增优化 <凉宫春日的忧郁>
标签:for 推出 can one nbsp include music 一个个 mes
原文地址:https://www.cnblogs.com/2018hzoicyf/p/11371304.html