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

30 篇文章 0 订阅
17 篇文章 0 订阅

首先要求的式子是一个斜率的相反数,其实就是求斜率的最大值,那么我们只需维护一个下凸包即可,
考虑到直接用栈来存,如果是在一条链上的话可以保证每个数只会被插入弹出一次,直接做,暴力退栈就行了。
然而在树上暴力退的话会被卡成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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值