• Tree Infection(CF)


    简而言之:
    一棵树,每秒钟你要做两个操作:

    传播:对于每个顶点v,如果v的至少一个孩子被感染,你可以通过感染你选择的v的至多一个其他孩子来传播疾病。

    注射:你可以选择任何一个健康的顶点,感染它。

    求最少的次数

    分析:很明显只关于一个节点儿子的个数为多少

    如果有x个点有儿子 那么至少需要x次 并且很明显儿子数量越多我们就要越先感染

    按照儿子个数排序从小到大 第一轮感染剩下的儿子分别为 sz[u]-i

    第一轮感染完成后 保证了每个节点的儿子都有病原体 剩下的问题就是我们感染操作和传播操作要同时进行

    模型变为 一个数列 每一秒 数列每个大于0的数都减一 此外每一秒你可以对一个元素额外减一

    我们从大到小枚举还需要的次数即可 这道题难点就在后面这个点

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) x&(-x)
    #define ll long long
    const int maxn=2e5+5;
    int n,x,T;
    int sz[maxn];
    vector<int>Q,S;
    int main(){
    	cin>>T;
    	while(T--){
    		cin>>n;
    		memset(sz,0,sizeof(sz));
    		Q.clear();S.clear();
    		Q.push_back(1);
    		for(int i=2;i<=n;i++)
    		scanf("%d",&x),sz[x]++;
    		for(int i=1;i<=n;i++)
    		if(sz[i])Q.push_back(sz[i]);
    		sort(Q.begin(),Q.end());
    		int cntt=Q.size();
    		for(int i=0;i<cntt;i++)
    		if(Q[i]-i-1>0)S.push_back(Q[i]-i-1);
    		int cnt=S.size();
    		if(cnt){
    		sort(S.begin(),S.end());
    		int res,j=cnt-1;
    		int tot=0;
    		for(int i=S[cnt-1];i>=1;i--){
    			while(j>=0&&S[j]>i)j--;
    			tot+=cnt-1-j;
    			if(tot<=i)res=i;
    			else break;
    		}		 
    		cout<<res+cntt<<endl;
    		}else cout<<cntt<<endl;
    	}
         return 0;
    }
  • 相关阅读:
    ETL概述
    POI操作Excel常用方法总结
    段的创建表user_segments
    定位导致物化视图无法快速刷新的原因
    在shell脚本中调用sqlplus
    Oracle 字符集的查看和修改
    Java Web发布
    JSP搭建
    完全卸载oracle11g步骤:
    剑指offer——二叉排序树(BST)、平衡二叉树(AVL)
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/16134349.html
Copyright © 2020-2023  润新知