zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    Android 按键消息处理Android 按键消息处理
    objcopy
    SQLite多线程读写实践及常见问题总结
    android动画坐标定义
    Android动画效果translate、scale、alpha、rotate
    Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
    Flatten Binary Tree to Linked List
    Distinct Subsequences
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/Mychael/p/9246390.html
Copyright © 2011-2022 走看看