BZOJ3835 [Poi2014]Supercomputer 【斜率优化】

题目链接

BZOJ3835

题解

对于\(k\),设\(s[i]\)为深度大于\(i\)的点数

\[ans = max\{i + \lceil \frac{s[i]}{k}\} \rceil \]

最优决策一定是一开始每一层拿不满\(k\)个点,然后之后一直往下拿的同时通过中间层剩余的点拿满\(k\)个点
我们就有前\(i\)层用了\(i\)次,后面每\(k\)个点用一次
容易证明合法的\(i\)得出的答案一定是最大的

然后式子化为

\[\lceil \frac{ik + s[i]}{k} \rceil \]

就是求\(ik + s[i]\)最大
斜率优化即可

复杂度\(O(n)\)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 1000005,maxm = 100005,INF = 1000000000;
inline int read(){
	int out = 0,flag = 1; char c = getchar();
	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
	return out * flag;
}
int n,Q,s[maxn],K[maxn],ls[maxn],rb[maxn],fa[maxn],dep[maxn];
int ans[maxn],q[maxn],head,tail,D;
void dfs(int u){
	s[dep[u]]++; D = max(D,dep[u] + 1);
	for (int k = ls[u]; k; k = rb[k]){
		dep[k] = dep[u] + 1;
		dfs(k);
	}
}
inline int C(int a,int b){return a / b + (a % b > 0);}
int main(){
	n = read(); Q = read();
	REP(i,Q) K[i] = read();
	for (int i = 2; i <= n; i++) fa[i] = read(),rb[i] = ls[fa[i]],ls[fa[i]] = i;
	dfs(1);
	for (int i = D; ~i; i--) s[i] += s[i + 1];
	head = 0; tail = -1;
	for (int i = D; ~i; i--){
		while (head < tail && 1ll * (i - q[tail]) * (s[q[tail]] - s[q[tail - 1]]) >= 1ll * (q[tail] - q[tail - 1]) * (s[i] - s[q[tail]])) tail--;
		q[++tail] = i;
	}
	for (int i = n; i; i--){
		while (head < tail && (s[q[head + 1]] - s[q[head]]) >= 1ll * i * (q[head] - q[head + 1])) head++;
		ans[i] = q[head] + C(s[q[head]],i);
	}
	REP(i,Q) printf("%d",K[i] > n ? D : ans[K[i]]),i < Q ? putchar(' ') : 0;
	return 0;
}

posted @ 2018-06-30 10:48  Mychael  阅读(243)  评论(0编辑  收藏  举报