Problem 1049: Lost My Music【可持久化棧+倍增】

首先要求的式子是一個斜率的相反數,其實就是求斜率的最大值,那麼我們只需維護一個下凸包即可,
考慮到直接用棧來存,如果是在一條鏈上的話可以保證每個數只會被插入彈出一次,直接做,暴力退棧就行了。
然而在樹上暴力退的話會被卡成O(N2 )……
所以對於每個點存一個倍增數組,記錄其在凸殼裏的祖先,然後亂搞即可……
代碼:

//#include <bits/stdc++.h>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <limits>
#include <map>
#include <vector>
#include <queue> 
#define LL long long
#define ft first
#define sd second
#define mp(x,y) make_pair(x,y)
#define db double
//#define int LL
using namespace std;
const int N   = 5e5+10;
//const int mod = ;
const db INF =numeric_limits<double >::max();

#define rep(i,x,y) for (int i=x;i<=y;++i)
void read(int &x)
{
    x=0;
    char ch=getchar();
    int f=1;
    while (!isdigit(ch))
       (ch=='-'?f=-1:0),ch=getchar();
    while ( isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    x*=f;
}

int c[N],fa[N],dep[N];
int head[N];
struct xx
{
    int V,next;
}b[N<<1];
int G,n;
void add(int x,int y)
{
    b[++G]=(xx){y,head[x]};
    head[x]=G;
}
db f[N];
#define F(x) for (int i=head[x];i;i=b[i].next)
#define v b[i].V

int q[N],hd,tl,nw;
int anc[N][20],x;

int ok(int xi,int yi,int xj,int yj,int xk,int yk)
{
    return (LL)(yj-yi)*(LL)(xk-xj)<=(LL)(yk-yj)*(LL)(xj-xi);
}

signed main()
{
    freopen("data.txt","r",stdin);
    freopen("Moon.txt","w",stdout);
    read(n);
    rep(i,1,n) 
        read(c[i]);
    rep(i,2,n) read(fa[i]),add(fa[i],i);
    //dfs(1,0);
    q[1]=1;hd=tl=1;
    while (hd<=tl)
    {
        nw=q[hd++];dep[nw]=dep[fa[nw]]+1;
        F(nw) q[++tl]=v;
        if (nw==1) continue;
        x=fa[nw];
        for (int i=2;i>=0;--i)
        {
            if (anc[ x][i]<=1) continue;
            if (!ok(dep[ anc[anc[x][i]][0] ],c[ anc[anc[x][i]][0] ],dep[anc[x][i]],c[anc[x][i]],dep[nw],c[nw]))
              x=anc[x][i];
        }
        if (x>1)
          if (!ok(dep[anc[x][0]],c[anc[x][0]],dep[x],c[x],dep[nw],c[nw]))
            x=anc[x][0];
        anc[nw][0]=x;
        rep(i,1,19) anc[nw][i]=anc[anc[nw][i-1]][i-1];

    }
    rep(i,2,n) printf("%.10f\n",(db)(c[anc[i][0]]-c[i])/(dep[i]-dep[anc[i][0]]));
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章