不会做看题解qwq,感觉这个结论…不知道怎么想啊qwq
用sum[i]表示层数>=i的点数,那么有
ans=maxi=1 to maxdep(i+⌈sum[i+1]k⌉)
这个柿子的意思是:用i次操作搞定前i层,接下来每次操作都能取满k个或把剩余不足k个取完
为什么答案就是这个呢…
首先答案不会比这个优了,因为每次操作最多搞定一层,所以i次操作搞定前i层是上限了,而剩下的每次操作又拿满,所以答案不会比这个更优
那么为什么不会比这个差呢
(我不严谨的证明一下,意会一下?
首先我们让dis[i]表示i子树最大深度,每次操作拿点的策略肯定是选dis[i]最大的,即能往下拓展最远的那些优先拓展(因为他们比较有前景qwq),其他的如果能取的点还有多的再考虑他们
那么先证i次操作能拿完前i层
假设我们用到的是值相同的,最小的i
假设i次拿不完前i层
那么一定是出现了这样的情况
(中间的节点懒得画了
(哇我画的是真的丑= =
即我们用j次操作拿完了前j层(j可以是1),然后第j+1到i层点太多了,i次操作取不完
那么一定有
⌈sum[j]−sum[i+1]k⌉>=⌈sum[i+1]k⌉+i−j
那么我们一定会取j而不是取i贡献答案,所以i次操作一定能拿完前i层
再证剩下每次操作都可以取满
如果我们剩下的操作有的取不满,导致了实际答案更大,一定是有类似这样的情况
就是用i次操作拿完了前i层,然后第i+1到k层的操作都顺利拿满了,然而k层到j层中间的节点很少,因为每次最多往下拓展一层,导致k层到j层的操作拿不满导致了答案增大,那么显然这时候i不能使ans取得max
所以也不会有这种情况,即剩下每次操作都能拿满
于是证明了这个柿子
ans=maxi=1 to maxdep(i+⌈sum[i+1]k⌉)
剩下的工作就简单了,画一下柿子
ans=max(⌈sum[i+1]+ikk⌉))
就是随着k变大,维护
sum[i+1]+ik
最大值
维护一个斜率单调的队列就行了
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
inline void read(int &x)
{
char c; while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
const int maxn = 1100000;
const double eps = 1e-9;
int n,Q;
int dep[maxn];
struct edge{int y,nex;}a[maxn<<1]; int len,fir[maxn];
inline void ins(const int x,const int y){a[++len]=(edge){y,fir[x]};fir[x]=len;}
void dfs(const int x,const int d)
{
dep[d]++;
for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y) dfs(a[k].y,d+1);
}
struct node{int x,y;}p[maxn],q[maxn]; int head,tail,pn;
inline ll multi(node x,node y,node z)
{
x.x-=z.x; x.y-=z.y;
y.x-=z.x; y.y-=z.y;
ll re=(ll)x.x*y.y-(ll)x.y*y.x;
if(re>0) re=1ll;
return re<0?-1:re;
}
inline bool cmp(node x,node y,int k) { return (double)(y.y-x.y)-(double)k*(y.x-x.x)>=eps; }
int ask[maxn],ans[maxn];
int main()
{
read(n); read(Q);
for(int i=1;i<=Q;i++) read(ask[i]);
for(int i=2;i<=n;i++)
{
int x; read(x);
ins(x,i);
}
dfs(1,1);
for(int i=n;i>=1;i--) dep[i]+=dep[i+1];
for(int i=1;i<=n&&dep[i];i++) p[++pn]=(node){i,-dep[i+1]};
head=1,tail=0;
for(int i=1;i<=pn;i++)
{
while(head<tail&&multi(q[tail],p[i],q[tail-1])<=0) tail--;
q[++tail]=p[i];
}
for(int k=1;k<maxn;k++)
{
while(head<tail&&!cmp(q[head],q[head+1],k)) head++;
ans[k]=q[head].x+(-q[head].y+k-1)/k;
}
for(int i=1;i<Q;i++) printf("%d ",ans[ask[i]]);
printf("%d\n",ans[ask[Q]]);
return 0;
}