zoukankan      html  css  js  c++  java
  • CF1436D Bandit in a City 题解

    思路

    一道CF题
    看题目很明显可以使用二分,但又想不到很好的judging函数
    所以考虑动态规划
    先考虑假如完全理想均分
    那么每个叶子节点可以被分到(lceilfrac{size[u]}{leaf[u]} ceil)
    (为什么是上取整(?)仔细想想
    那么现在我们能进行分配的只有当前节点权值
    如果每个子节点都小于(lceilfrac{size[u]}{leaf[u]} ceil)
    那么就意味着我们可以对每个点稍微加上那么点权值,使得它们都达到(lceilfrac{size[u]}{leaf[u]} ceil)左右
    那么若存在最大点大于(lceilfrac{size[u]}{leaf[u]} ceil),我们肯定不会再向这个点加权,
    再加权只会让答案变得更劣,所以要尽量"浪费"掉手中的权值,

    动态规划方程

    (mxn[x]以x为子树中最大的叶子节点,size[x]x子树中的权值和,leaf[x]x子树中的叶节点个数)

    [mxn[x] = max({mxn[y] , lceilfrac{size[u]}{leaf[u]} ceil }) ]

    Code

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    
    using namespace std;
    
    #define int long long 
    
    const int p=2e5+5;
    
    template<typename _T>
    inline void read(_T &x)
    {
    	x=0;char s=getchar();int f=1;
    	while(s<'0'||'9'<s){f=1;if(s=='-')f=-1;s=getchar();}
    	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
    	x*=f;
    }
    
    int head[p],nxt[p*2],ver[p*2];
    int point[p];
    int tit;
    
    int leaf[p],mxn[p],size[p];
    
    inline void add(int x,int y)
    {
    	ver[++tit] = y;
    	nxt[tit] = head[x];
    	head[x] = tit;
    }
    
    inline void dfs(int now,int fa)
    {
    	size[now] = point[now];
    	int cnt=0;
    	
    	for(int v,i=head[now];i;i=nxt[i])
    	{
    		if(ver[i] == fa) continue;
    		v=ver[i];
    		dfs(v,now);
    		size[now] += size[v];
    		leaf[now] += leaf[v];
    		mxn[now] = max(mxn[now] , mxn[v]);
    		cnt++;
    	}
    	
    	if(cnt == 0) mxn[now] = point[now],leaf[now]=1;
    	
    }
    
    inline void bfs(int now,int fa)
    {
    	for(int i=head[now];i;i=nxt[i])
    	{
    		int v=ver[i];
    		if(v == fa) continue;
    		bfs(v,now);
    		mxn[now] = max(mxn[now] , max(mxn[v] , (int)ceil((double)size[now]/leaf[now])));
    	}
    }
    
    signed main()
    {
    	
    	int n;
    	
    	read(n);
    	
    	for(int i=2,pi;i<=n;i++)
    	{
    		read(pi);
    		
    		add(i,pi);
    		add(pi,i);
    	}
    	
    	for(int i=1;i<=n;i++) read(point[i]);
    	
    	dfs(1,0);
    	
    	bfs(1,0);
    	
    	cout<<mxn[1];
    	
    }
    
  • 相关阅读:
    IntelliJ IDEA 编译方式介绍
    IntelliJ IDEA 缓存和索引介绍和清理方法
    无线鼠标没反应了
    L1-039 古风排版 (20 分)
    L1-043 阅览室 (20 分)
    数学思想
    输入
    2018年湘潭大学程序设计竞赛 E 吃货
    问题 1936: [蓝桥杯][算法提高VIP]最大乘积
    指针 链表
  • 原文地址:https://www.cnblogs.com/-Iris-/p/13928883.html
Copyright © 2011-2022 走看看