zoukankan      html  css  js  c++  java
  • [BZOJ2067]szn

    description

    BZOJ权限题.

    solution

    一道非常好的二分+贪心题目。
    第一问就是(frac{sum_u(deg[u]-1)}{2}+1)

    第二问需要在方案最优的情况下最长链最短,考虑二分。
    那么自底向上地考虑每个子树中的节点,
    我们发现每个节点要产生最优方案,一定是考虑选择自己伸向父亲的链和合并儿子伸向自己的链。

    于是我们把所有儿子伸向自己的链长排序,
    那么我们需要在合并的链长不超过二分答案的情况下使得伸向父亲的链长最小。
    由于伸向父亲链长越小合并答案越不容易满足,因此考虑二分这个伸向父亲的链长。
    总复杂度为(O(nlog^2n))

    Code

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<ctime>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define Cpy(x,y) memcpy(x,y,sizeof(x))
    #define Set(x,y) memset(x,y,sizeof(x))
    #define FILE "a"
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const dd eps=1e-7;
    const int N=300010;
    const int M=1000010;
    const int inf=2147483647;
    const ll INF=1e18+1;
    const ll P=100000;
    il ll read(){
    	RG ll data=0,w=1;RG char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
    	return data*w;
    }
    
    il void file(){
    	srand(time(NULL)+rand());
    	freopen(FILE".in","r",stdin);
    	freopen(FILE".out","w",stdout);
    }
    
    int n;
    int head[N],nxt[N<<1],to[N<<1],cnt,d[N];
    int c,flg;
    
    int f[N];VI L[N];
    il int pick(int k,int fb){
    	RG int len=L[k].size(),mx=0;
    	if(!((len&1)^(fb==-1))){if(fb==len-1)len--;mx=L[k][len-1];len--;}
    	for(RG int i=0,j=len-1;i<=j;i++,j--){
    		if(i==fb)i++;if(j==fb)j--;if(i>j)break;
    		mx=max(mx,L[k][i]+L[k][j]);
    	}
    	return mx;
    }
    void dfs(int u,int ff){
    	f[u]=0;L[u].clear();
    	for(RG int i=head[u];i;i=nxt[i]){
    		RG int v=to[i];if(v==ff)continue;
    		dfs(v,u);if(!flg)return;
    		L[u].push_back(f[v]+1);
    	}
    	
    	sort(L[u].begin(),L[u].end());
    	
    	if(!ff){if(pick(u,-1)>c){flg=0;return;}return;}
    	else if((d[u]&1)&&pick(u,-1)<=c)return;
    	RG int l=0,r=L[u].size()-1,mid;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(pick(u,mid)<=c)f[u]=L[u][mid],r=mid-1;
    		else l=mid+1;
    	}
    	if(!f[u]){flg=0;return;}
    }
    
    il bool check(int w){c=w;flg=1;dfs(1,0);return flg;}
    
    int main()
    {
    	n=read();
    	for(RG int i=1,u,v;i<n;i++){
    		u=read();v=read();d[u]++;d[v]++;
    		to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
    		to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;
    	}
    	RG int l=1,r=n-1,mid,ans=n,ret=0;
    	for(RG int i=1;i<=n;i++)ret+=(d[i]-1)/2;ret++;
    	while(l<=r){
    		mid=((l+r)>>1);
    		if(check(mid))ans=mid,r=mid-1;
    		else l=mid+1;
    	}
    	printf("%d %d
    ",ret,ans);
    	return 0;
    }
    
    
    
  • 相关阅读:
    js进阶 12-7 pageY和screenY以及clientY的区别是什么
    printf交替使用
    【iOS发展-81】setNeedsDisplay刷新显卡,并CADisplayLink它用来模拟计时器效果
    android tv 全屏幕垂直画
    uva 10305
    (札记)Java应用架构设计-模块化模式与OSGi
    《学习opencv》笔记——矩阵和图像处理——cvAnd、cvAndS、cvAvg and cvAvgSdv
    一旦专利
    SharePoint 2010 升级到2013时间 为了确保用户可以连接,但无法改变升级数据
    [TroubleShooting] The remote copy of database xx has not been rolled forward to a point in time
  • 原文地址:https://www.cnblogs.com/cjfdf/p/9688627.html
Copyright © 2011-2022 走看看