• CF1039D-You Are Given a Tree【根号分治,贪心】


    正题

    题目链接:https://www.luogu.com.cn/problem/CF1039D


    题目大意

    给出(n)个点的一棵树,然后对于(kin[1,n])求每次使用一条长度为(k)的链覆盖树并且不能重复覆盖点时最大覆盖条数。

    (1leq nleq 10^5)


    解题思路

    先考虑暴力怎么做,因为每条链的价值都是一,显然的一种贪心思想是能合并的就合并(没有让出一条链给另一条链腾空间的必要)。

    这样的复杂度是(O(n))的,但是对于每个都要求所以需要优化。

    之后考虑上根号分治,对于一个(k)的答案显然不会超过(frac{n}{k}),所以可以当(kleq sqrt n)的时候暴力做,然后由于答案递增,大于(sqrt n)(k)答案的取值不会超过(sqrt n),每次二分断点即可。时间复杂度(O(nsqrt nlog n))

    其实发现这样还是不够快,可以找到一个更好的阈值,设为(T),那么前面的复杂度就是(T),后面的复杂度就是(frac{n}{T}log n),用平衡规划的思想当(T=frac{n}{T}log n)时最快,也就是(T=sqrt{nlog n})时最快了。


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=1e5+10;
    struct node{
    	int to,next;
    }a[N<<1];
    int n,tot,cnt,dfn[N],ls[N],fa[N],f[N];
    void addl(int x,int y){
    	a[++tot].to=y;
    	a[tot].next=ls[x];
    	ls[x]=tot;return;
    }
    void dfs(int x){
    	dfn[++cnt]=x;
    	for(int i=ls[x];i;i=a[i].next){
    		int y=a[i].to;
    		if(y==fa[x])continue;
    		fa[y]=x;dfs(y);
    	}
    	return;
    }
    int solve(int k){
    	if(k==1)return n;
    	int ans=0;
    	for(int i=1;i<=n;i++)f[i]=1;
    	for(int i=n;i>=1;i--){
    		int x=dfn[i];
    		if(f[x]&&f[fa[x]]){
    			if(f[x]+f[fa[x]]>=k)
    				ans++,f[fa[x]]=0;
    			else f[fa[x]]=max(f[fa[x]],f[x]+1);
    		}
    	}
    	return ans;
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<n;i++){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		addl(x,y);addl(y,x);
    	}
    	dfs(1);
    	int T=sqrt((double)n*(log(n)/log(2))),last,z=T+1;
    	for(int i=1;i<=T;i++)printf("%d
    ",last=solve(i));
    	while(z<=n){
    		int l=z+1,r=n,k=solve(z);
    		while(l<=r){
    			int mid=(l+r)>>1;
    			if(solve(mid)<k)r=mid-1;
    			else l=mid+1;
    		}
    		for(int i=z;i<=r;i++)
    			printf("%d
    ",k);
    		z=r+1;
    	}
    	return 0;
    }
    
  • 相关阅读:
    英文半字节压缩编码技术
    博弈翻硬币游戏
    POJ 2015 Permutation Code
    8051、ARM和DSP指令周期的测试与分析
    Huffman编码
    CentOS 命令提示符颜色及样式详解
    JAVA程序员面试32问
    面向抽象编程:接口和抽象类
    初学实用:实例讲解Java中的接口的作用
    C#和Java的区别
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15343702.html
Copyright © 2020-2023  润新知