zoukankan      html  css  js  c++  java
  • 【bzoj1758】 Wc2010—重建计划

    http://www.lydsy.com/JudgeOnline/problem.php?id=1758 (题目链接)

    题意

      给出一棵树,每条边有边权,问选出一条长度为$[L,U]$的路径,使得路径上的边权平均数最大是多少。

    Solution

      哈哈,爸爸终于过啦。

      首先二分答案,然后路径统计显然点分治,统计答案的时候单调队列维护一下滑动窗口里面的最值。因为要点分治若干次,我们不妨将重心预处理出来,减少常数。

      一定要小心,在点分治处理子树的时候,一定要按照深度从小到大的顺序处理,不然直接被新加的那组扫把型的数据卡掉T_T。

    细节

      清空cnt。

    代码

    // bzoj1758
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define LL long long
    #define LD long double
    #define eps 1e-4
    #define inf (1ll<<60)
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
    using namespace std;
    
    const int maxn=100010;
    int n,m,U,L,cnt,head[maxn];
    struct edge {int to,next,w;}e[maxn<<1];
    struct data {
    	int num,D;
    	friend bool operator < (data a,data b) {return a.D>b.D;}
    };
    
    namespace NodeDivide {
    	int Dargen,rt,D,maxD,sum,size[maxn],vis[maxn],Sum[maxn],f[maxn],q[maxn],h[maxn];
    	edge t[maxn];
    	double ans,deep[maxn],dis[maxn],Dis[maxn];
    	void link(int u,int v) {t[++cnt]=(edge){v,h[u]};h[u]=cnt;}
    	void dfs(int x,int fa) {
    		size[x]=f[x]=1;
    		for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa && !vis[e[i].to]) {
    				dfs(e[i].to,x);
    				f[x]=max(f[x],size[e[i].to]);
    				size[x]+=size[e[i].to];
    			}
    		f[x]=max(f[x],sum-size[x]);
    		if (f[x]<f[rt]) rt=x;
    	}
    	void caldeep(int x,int fa,int d) {
    		D=max(D,d);
    		for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa && !vis[e[i].to]) {
    				deep[e[i].to]=deep[x]+e[i].w;
    				caldeep(e[i].to,x,d+1);
    			}
    	}
    	void caldis(int x,int fa,int d) {
    		dis[d]=max(dis[d],deep[x]);
    		for (int i=head[x];i;i=e[i].next)
    			if (e[i].to!=fa && !vis[e[i].to]) caldis(e[i].to,x,d+1);
    	}
    	void solve(int x,double res) {
    		vis[x]=1;maxD=0;
    		priority_queue<data> T;
    		for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) {
    				D=0;deep[e[i].to]=e[i].w;
    				caldeep(e[i].to,x,1);
    				T.push((data){e[i].to,D});
    			}
    		while (!T.empty()) {
    			data tmp=T.top();T.pop();
    			caldis(tmp.num,x,1);
    			int l=1,r=0,pl=maxD,pr=maxD;
    			for (int i=1;i<=tmp.D;i++) {
    				for (;pl>-1 && pl>=L-i;pl--) {
    					while (l<=r && Dis[q[r]]-q[r]*res<Dis[pl]-pl*res) r--;
    					q[++r]=pl;
    				}
    				for (;pr>-1 && pr>U-i;pr--) while (l<=r && q[l]>=pr) l++;
    				if (pl<pr) ans=max(ans,dis[i]-i*res+Dis[q[l]]-q[l]*res);
    			}
    			maxD=max(maxD,tmp.D);
    			for (int i=1;i<=tmp.D;i++) Dis[i]=max(Dis[i],dis[i]),dis[i]=0;
    		}
    		for (int i=1;i<=maxD;i++) Dis[i]=0;
    		for (int i=h[x];i;i=t[i].next) if (Sum[t[i].to]>=L) solve(t[i].to,res);
    		vis[x]=0;
    	}
    	void caldargen(int x,int fa) {
    		vis[x]=1;
    		if (fa) link(fa,x);else Dargen=x;
    		for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) {
    				sum=size[e[i].to],rt=0;
    				dfs(e[i].to,x);
    				Sum[rt]=sum;
    				caldargen(rt,x);
    			}
    		vis[x]=0;
    	}
    	void Init() {
    		cnt=0;
    		sum=n;f[rt=0]=1<<30;
    		dfs(1,0);Sum[rt]=sum;
    		caldargen(rt,0);
    	}
    	double main(double res) {
    		ans=-inf;
    		solve(Dargen,res);
    		return ans;
    	}
    }
    using namespace NodeDivide;
    
    void link(int u,int v,int w) {
    	e[++cnt]=(edge){v,head[u],w};head[u]=cnt;
    	e[++cnt]=(edge){u,head[v],w};head[v]=cnt;
    }
    int main() {
    	scanf("%d%d%d",&n,&L,&U);
    	for (int u,v,w,i=1;i<n;i++) {
    		scanf("%d%d%d",&u,&v,&w);
    		link(u,v,w);
    	}
    	Init();
    	double l=0,r=1000000,ans;
    	while (l<=r) {
    		double mid=(l+r)/2;
    		if (main(mid)>=0) l=mid+eps,ans=mid;
    		else r=mid-eps;
    	}
    	printf("%.3lf",ans);
    	return 0;
    }
    
  • 相关阅读:
    JS实现倒计时
    jQuery图片展示插件Galleria
    几个常用的方法
    整理了一个多数据库通用操作类
    Oracle 伪列、取前几条记录、日期判断等
    第十九章 10头节点类,中间节点类和尾节点类 简单
    第十八章 38总结 简单
    第十九章 代码重用 6按别名传递book对像 简单
    第十九章 代码重用 3类书类 简单
    第十九章 代码重用 4为图书重载GetAuthor函数 简单
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6510054.html
Copyright © 2011-2022 走看看