把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P3571 [POI2014]SUP-Supercomputer

题面传送门

感觉考场上不一定做得出来的题目?

首先我们可以得到每个点的深度,然后猜测这个只和每个层的深度有关。

我们考虑这样一个贪心:对于每一层的每个点,如果这个点有子节点,那么优先搞这个点,否则先放一放,这样可以保证如果点数足够,那么能操作的点数是递增的,如果操作的点数不递增,那么显然无论什么操作都最优只能做到这样。

则我们统计出当前层的的点数,并设\(f_i\)为操作到第\(i\)步的时候最少能剩下的点数,则\(f_i=\max(f_{i-1}+q_i-k,0)\)。可以做到\(O(nq)\)

实际上可以发现是一条斜线截凸包的形式,则可以斜率优化,时间复杂度\(O(n+q)\)

code:

#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=1e6+5,M=pow(6,10)+5,K=2e3+5,mod=998244353,Mod=mod-1;const db eps=1e-5;const int INF=1e9+7;
int n,m,k,x,y,z,Mx,d[N],A[N],Fl[N],Ct,ToT,st[N],sh,H,Ans[N];
db slope(int x,int y){return (Fl[y]-Fl[x])*1.0/(y-x);}
int main(){
	freopen("1.in","r",stdin);
	int i,j;scanf("%d%d",&n,&m);for(i=1;i<=m;i++)scanf("%d",&A[i]);d[1]=1;for(i=2;i<=n;i++) scanf("%d",&x),d[i]=d[x]+1,Fl[d[i]]++,Mx=max(Mx,d[i]);
	Fl[1]=1;for(i=1;i<=Mx;i++) Fl[i]+=Fl[i-1];for(i=1;i<=Mx;i++) {while(sh>1&&slope(st[sh-1],st[sh])>slope(st[sh],i)) sh--;st[++sh]=i;}
	H=1;for(i=1;i<=n;i++){while(H^sh&&slope(st[H],st[H+1])<i) H++;Ans[i]=Fl[st[H]]+1ll*(Mx-st[H])*i;}for(i=1;i<=m;i++) printf("%d ",(n-Ans[min(A[i],n)]+A[i]-1)/A[i]+Mx);
}
posted @ 2022-10-05 19:30  275307894a  阅读(26)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end