一道神仙好题。

首先看到有多组\(k\),第一反应就是离线。

考虑贪心。

我们每次一定是尽量选择有儿子的节点。以便于我们下一次扩展。

但是对于一个\(k\),每次贪心的复杂度是\(O(n)\)

总复杂度是\(O(nq)\),肯定过不了。

qwq

那我们只能来考虑一个快速求一个\(k\)的答案。

感觉题解的柿子好神仙啊。

这里定义\(f[i]\)表示\(k=i\)的时候的最小次数。

\(sum[i]\)表示深度大于等于\(i\)的点有多少个。

则$$f[i]=max(j+\lceil \frac{sum[j+1]}{i} \rceil)$$

含义是用了\(i\)次把全\(i\)层都取掉,然后剩下的每次都能取满。

qwq现在来解释一下为什么是这个柿子。

首先,比较容易证明答案一定在所有的\((j+\lceil \frac{sum[j+1]}{i} \rceil\)中,因为这已经是最优情况了(前i次最多取i层,而后面也是每次取满,所以一定是最优的情况,不存在更优秀的情况。)

那么为什么是要取\(max\)呢。

是为了避免不合法的情况。

这里不合法的情况有两种情况,首先是前\(i\)次取不满\(前i层\)。那么如果存在这个情况,一定存在\(j\)使得,前\(j\)层能够\(j\)次取满,但是\(j到i\)不能用\(j-i\)取满,则存在等式

\[\lceil \frac{sum[j+1]}{k} \rceil > \lceil \frac{sum[i+1]}{k} \rceil + (i-j)
\]
\[\lceil \frac{sum[j+1]}{k} \rceil + j> \lceil \frac{sum[i+1]}{k} \rceil + i
\]

那么取\(max\),这种不合法的情况就能排除。

另一种不合法的情况就是,后面的次数并不能每次都取满。

如果上面的情况合法,那么一定存在$$\lceil \frac{sum[i+1]-sum[i+x+1]}{k} \rceil + i+x+1 > \lceil \frac{sum[i+1]}{k} \rceil + i$$

因为存在一层满足不能够一次用满k,且没有多余的东西让他选,那这时候等式左边的\(i+x+1\)等于该层的时候,一定比原本的柿子更大。

至于为什么不存在一个小于\(max\)并且合法的情况,是因为一层最少需要一次。而如果存在\(min\),说明要满足用小于\(j\)次,选完\(j\)层,而这个东西是不可能的。

qwq

那么证明到这里,大概能说明上述的柿子的是对的了。

也就是

\[f[i]=max(j+\lceil \frac{sum[j+1]}{i} \rceil)
\]

那接下来应该怎么优化呢。

我们将上述柿子进行变形

\[f[i]=max(\lceil \frac{j\times i+ sum[j+1]}{i} \rceil)
\]

那么如果存在一个\(j>k\)且\(j比k\)优秀的话,应该满足

\[j\times i + sum[j+1] > k \times i + sum[k+1]
\]

经过化简,$$\frac{sum[j+1]-sum[k+1]}{j-k}>-i$$

直接上斜率优化就好

\(sum\)数组可以直接通过前缀和求出来

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk make_pair
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 1e6+1e2;
int sum[maxn];
int n,m;
int point[maxn],nxt[maxn],to[maxn];
int cnt;
int deep[maxn];
int dp[maxn];
int a[maxn];
void addedge(int x,int y)
{
nxt[++cnt]=point[x];
to[cnt]=y;
point[x]=cnt;
}
struct Point{
ll x,y,num;
};
Point q[maxn];
ll chacheng(Point x,Point y)
{
return x.x*y.y-x.y*y.x;
}
bool Count(Point i,Point j,Point k)
{
Point x,y;
x.x=k.x-i.x;
x.y=k.y-i.y;
y.x=k.x-j.x;
y.y=k.y-j.y;
if (chacheng(x,y)>=0) return true;
return false;
}
int head=1,tail=0;
void push(Point x)
{
while(tail>=head+1 && Count(q[tail-1],q[tail],x)) tail--;
q[++tail]=x;
}
void pop(int lim)
{
while(tail>=head+1 && q[head+1].y-q[head].y>lim*(q[head+1].x-q[head].x)) head++;
}
int mx;
void dfs(int x,int dep)
{
deep[dep]++;
mx=max(mx,dep);
for (int i=point[x];i;i=nxt[i])
{
int p = to[i];
dfs(p,dep+1);
}
}
int qq;
int main()
{
n=read();qq=read();
int ymh =0;
for (int i=1;i<=qq;i++) a[i]=read(),ymh=max(ymh,a[i]);
for (int i=2;i<=n;i++)
{
int x=read();
addedge(x,i);
}
dfs(1,1);
for (int i=mx;i>=0;i--)
{
deep[i]+=deep[i+1];
}
for (int i=0;i<mx;i++)
push((Point){i,deep[i+1],i}); for (register int i=1;i<=ymh;++i)
{
pop((-1)*i);
int now = q[head].num;
dp[i]=now+((deep[now+1]-1)/i)+1;
}
for (int i=1;i<=qq;i++) cout<<dp[a[i]]<<" ";
return 0;
}

洛谷3571 POI2014 SUP-Supercomputer (斜率优化)的更多相关文章

  1. 洛谷P2365 任务安排(斜率优化dp)

    传送门 思路: 最朴素的dp式子很好考虑:设\(dp(i,j)\)表示前\(i\)个任务,共\(j\)批的最小代价. 那么转移方程就有: \[ dp(i,j)=min\{dp(k,j-1)+(sumT ...

  2. 洛谷P2120 [ZJOI2007]仓库建设 斜率优化DP

    做的第一道斜率优化\(DP\)QwQ 原题链接1/原题链接2 首先考虑\(O(n^2)\)的做法:设\(f[i]\)表示在\(i\)处建仓库的最小费用,则有转移方程: \(f[i]=min\{f[j] ...

  3. 【洛谷p3994】Highway 二分+斜率优化DP

    题目大意:给你一颗$n$个点的有根树,相邻两个点之间有距离,我们可以从$x$乘车到$x$的祖先,费用为$dis\times P[x]+Q[x]$,问你除根以外每个点到根的最小花费. 数据范围:$n≤1 ...

  4. 洛谷P4027 [NOI2007]货币兑换(dp 斜率优化 cdq 二分)

    题意 题目链接 Sol 解题的关键是看到题目里的提示... 设\(f[i]\)表示到第\(i\)天所持有软妹币的最大数量,显然答案为\(max_{i = 1}^n f[i]\) 转移为\(f_i = ...

  5. 洛谷P4072 [SDOI2016]征途(斜率优化)

    传送门 推式子(快哭了……)$$s^2*m^2=\sum _{i=1}^m (x_i-\bar{x})^2$$ $$s^2*m^2=m*\sum _{i=1}^m x_i^2-2*sum_n\sum ...

  6. 【洛谷 P5017】 摆渡车(斜率优化)

    题目链接 算是巩固了一下斜率优化吧. 设\(f[i]\)表示前\(i\)分钟最少等待时间. 则有\(f[i]=\min_{j=0}^{i-m}f[j]+(cnt[i]-cnt[j])*i-(sum[i ...

  7. 洛谷P4983 忘情 (WQS二分+斜率优化)

    题目链接 忘情水二分模板题,最优解对划分段数的导数满足单调性(原函数凸性)即可使用此方法. 详细题解洛谷里面就有,不啰嗦了. 二分的临界点让人有点头大... #include<bits/stdc ...

  8. 洛谷4072 SDOI2016征途 (斜率优化+dp)

    首先根据题目中给的要求,推一下方差的柿子. \[v\times m^2 = m\times \sum x^2 - 2 \times sum \times sum +sum*sum \] 所以\(ans ...

  9. 洛谷 P3580 - [POI2014]ZAL-Freight(单调队列优化 dp)

    洛谷题面传送门 考虑一个平凡的 DP:我们设 \(dp_i\) 表示前 \(i\) 辆车一来一回所需的最小时间. 注意到我们每次肯定会让某一段连续的火车一趟过去又一趟回来,故转移可以枚举上一段结束位置 ...

随机推荐

  1. Ubuntu 配置、使用samba共享文件夹

    安装库 sudo apt install smbclient samba samba-common 启动samba sudo /etc/init.d/samba start 备份配置文件 sudo c ...

  2. 前端使用a标签启动本地.exe程序

    目录 1,需求 2,效果图 3,实现原理 4,代码 5,注意事项 1,需求 最近有一个需求,在web页面上有一个按钮,点击按钮,调起本地的.exe程序客户端,我在网上找了很多,感觉都不完整,所以自己总 ...

  3. Python之struct模块

    面对网络协议,在组包拆包时,python提供了struct模块,它可以帮助我们在python值和C语言的结构体之间相互转换,下面一起来了解struct的具体用法. 假设,我们的网络协议为消息id(un ...

  4. hibernate01

    什么是hibernate ORM框架/持久层框架 jdbc的一个框架 object reference mapping 通过管理对象来改变数据库中的数据 通过管理对象来操作数据库 hibernate的 ...

  5. jq的选择器中带有特殊符号无法获取元素

    因项目需要,将元素id命名为数组(array[i].string) 使用jq去获取该id的元素时,返回的是个undefined.即jq获取不到该元素,因为该元素中的id含有特殊字符"[&qu ...

  6. OSS对象存储的文件上传、解冻、下载与查看

    上传文件 cp命令用于上传.下载.拷贝文件. # 语法 ./ossutil cp [-r] file_url cloud_url # 例如 ossutil64 cp -r /remote/closed ...

  7. throw关键字

    1.基础用法 2.方法中加合法校验,告知方法的调用者 数组越界判断 3.一切皆为对象,创建的是运行期对象,则可以不处理(throws/try catch),直接交给JVM处理(打印并终止程序) 4.O ...

  8. pygame简单小游戏 移动小球

    键盘a,d,s,w移动小球 需要安装pygame cmd里输入pip install pygame import pygame import sys pygame.init() screen = py ...

  9. Spring框架(第一天)

    一. 引言 a) 什么是Spring框架?(spring官网:www.springsource.org) 3.x  不提供第三发依赖jar 目前已经到了5.x版本. Spring轻量级(代码入侵性小) ...

  10. PHP匿名类的用法

    在PHP7之后,PHP中加入了匿名类的特性.匿名类和匿名方法让PHP成为了更现代化的语言,也让我们的代码开发工作越来越方便.我们先来看看匿名类的简单使用. // 直接定义 $objA = new cl ...