• BZOJ3835 [Poi2014]Supercomputer 【斜率优化】


    题目链接

    BZOJ3835

    题解

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

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

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

    然后式子化为

    [lceil frac{ik + s[i]}{k} ceil ]

    就是求(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;
    }
    
    
  • 相关阅读:
    .OBJ est1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
    线程详细剖析(四)
    线程详细剖析(三)
    线程详细剖析(二)
    线程详细剖析(一)
    CAN总线相关的几个gitlab代码
    进程详细剖析(三)
    C++实现多级排序
    C/C++读写二进制文件
    C++11新特性
  • 原文地址:https://www.cnblogs.com/Mychael/p/9246390.html
Copyright © 2020-2023  润新知