• 【BZOJ5252】【洛谷P4383】【2018九省联考】—林克卡特树(二分+树形dp)


    毒瘤BZOJ1s传送门

    洛谷传送门

    题意有点复杂,实际上就是在求n+1n+1条链,使其长度和最大

    考虑60分的dp
    f[i][j]f[i][j]表示ii的子树有jj条链时的最大长度
    发现这个几乎无法dp对吧

    考虑到链上的点度数必然小于3
    再加一维表示ii的度数

    发现现在就很好维护了
    分类讨论一下就可以了

    但100分时k太大了
    O(nk)O(nk)无法承受

    但如果我们把11~kk时的ff打出来会发现这是一个上凸函数
    就可以带权二分解决了

    不会带权二分可以看这里

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=3e5+5;
    const int infr=1e9;
    const ll inf=1e12;
    int n,k,cnt,adj[N],nxt[N<<1],to[N<<1];
    struct dp{
    	ll val;int k;
    	dp(ll _val=0,int _k=0){
    		val=_val,k=_k;
    	}
    	friend inline bool operator <(const dp &a,const dp &b){
    		return (a.val==b.val)?(a.k>b.k):(a.val<b.val);
    	}
    	friend inline dp operator +(const dp &a,const dp &b){
    		return dp(a.val+b.val,a.k+b.k);
    	}
    }f[N][3],tr[3];
    ll l,r,mid,val[N<<1];
    inline void addedge(int u,int v,int w){
    	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w;
    }
    inline void init(){
    	for(int i=1;i<=n;i++)f[i][0]=dp(0,0),f[i][1]=dp(-inf,infr),f[i][2]=dp(-mid,1);
    }
    inline void dfs(int u,int fa){
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];ll va=val[e];
    		if(v==fa)continue;dfs(v,u);
    		for(int i=0;i<3;i++)tr[i]=dp(-inf,infr);
    		for(int i=0;i<3;i++)tr[0]=max(tr[0],f[u][0]+f[v][i]);
    		tr[1]=max(tr[1],f[u][0]+f[v][0]+dp(va-mid,1));
    		tr[1]=max(tr[1],f[u][0]+f[v][1]+dp(va,0));
    		for(int i=0;i<3;i++)tr[1]=max(tr[1],f[u][1]+f[v][i]);
    		tr[2]=max(tr[2],f[u][1]+f[v][0]+dp(va,0));
    		tr[2]=max(tr[2],f[u][1]+f[v][1]+dp(va+mid,-1));
    		for(int i=0;i<3;i++)tr[2]=max(tr[2],f[u][2]+f[v][i]);
    		for(int i=0;i<3;i++)f[u][i]=tr[i];
    	}
    }
    int main(){
    	n=read(),k=read();
    	for(int i=1;i<n;i++){
    		int u=read(),v=read(),w=read();
    		addedge(u,v,w),addedge(v,u,w);
    	}
    	l=-inf,r=inf;
    	while(l<r){
    		mid=(double)(l+r)/2-0.5,init(),dfs(1,0);
    		dp now=max(f[1][0],max(f[1][1],f[1][2]));
    		if(now.k==k+1){cout<<(now.val+(k+1)*mid);return 0;}
    		if(now.k>k+1)l=mid+1;else r=mid;
    	}
    	mid=l,init(),dfs(1,0);dp now=max(f[1][0],max(f[1][1],f[1][2]));
    	cout<<(now.val+(k+1)*mid);
    }
    
    
  • 相关阅读:
    [国嵌笔记][001-003][嵌入式系统概述]
    世界第一魔法师
    详解CSS display:inline-block的应用(转)
    详解CSS float属性(转)
    CSS代码重构与优化之路(转)
    未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。(转)
    【总结整理】display与position之间的关系【较完整】(转)
    css知多少(11)——position(转)
    【总结整理】行内标签span设置position:absolute/float属性可以设置宽度与高度
    【总结整理】display、visibility、overflow的隐藏问题
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145645.html
Copyright © 2020-2023  润新知