Description

Input

第 一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai,Bi,Vi分别表示道路(Ai,Bi),其价值为Vi 其中城市由1..N进行标号

Output

输出最大平均估值,保留三位小数

Sample Input

4
2 3
1 2 1
1 3 2
1 4 3

Sample Output

2.500

HINT

N<=100000,1<=L<=U<=N-1,Vi<=1000000 新加数据一组 By leoly,但未重测..2016.9.27

Source

这个WC题与一道WG的题贼像!!!

然后这题的套路据说又与wfj_2048大佬的middle贼像!!!

这种求平均值和中位数的套路就是二分,具体对于这个题来说二分一个平均值,把所有的边的边权减去mid

剩下的就是判断是否有一条长度在[L,R]间的路权值大于0;也就是说求长度在[L,R]间的权值最大的边

我个傻逼想到这里就GG了,然后就只能堕落了,于是去翻了翻LightGod的博客,Orz,太厉害了

对于一个点,一条路径只有经过这个点,或不经过这个点两种情况,不经过这个点的情况就往下递归,我们考虑经过这个点的情况

对于一条简单路径,他必定是在这个点的子树中选取两条不在同一子树中的路径进行相加

于是这个东西可以用单调队列来维护一个滑动窗口,(ANS[i]记录长度为i的权值最大的路径)

具体做法是这样:

我们考虑这个点的每个儿子管理的连通块(在每个儿子getdis的时候把该儿子管辖下的连通块中每个长度的权值最大值记录下来)

那么我们枚举处理该儿子的记录下来的边(每个长度的权值最大的边),假设长度为i,那么对于其他子树中长度的取值范围就是[L-i,R-i];

然后我们用普通单调队列的处理,处理完后这个儿子后再拿这个儿子的所有边去更新ANS.

对于每个点可以O(size)维护该点的最优值;

然后这个题就打完了...然后调了好久,是一个函数名打错了

附上代码:

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<set>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#define lson num<<1
#define rson num<<1|1
#define deepmaxlen dml
using namespace std;
typedef long long ll;
const int N=500050;
const int Inf=2147483647;
const double eps=1e-5;
int gi()
{
int x=0,flag=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*flag;
}
int head[N],to[N],nxt[N];
int size[N],f[N],deep[N],rt[N],vis[N],q[N];
double dml[N],ANS[N],ans=-Inf,c[N],dis[N];
int SIZE,root,cnt,tot,tot2,L,R,M_DEP,n;
struct data{
int id,dep;
}son[N];
bool cmp(data a,data b){
return a.dep<b.dep;
}
void lnk(int x,int y,int v){
to[++cnt]=y,c[cnt]=(double)v,nxt[cnt]=head[x],head[x]=cnt;
to[++cnt]=x,c[cnt]=(double)v,nxt[cnt]=head[y],head[y]=cnt;
}
void getroot(int x,int fa){
size[x]=1;f[x]=0;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(!vis[y]&&y!=fa){
getroot(y,x);
size[x]+=size[y];
f[x]=max(f[x],size[y]);
}
}
f[x]=max(f[x],SIZE-size[x]);
if(f[x]<f[root]) root=x;
}
void get_maxdis(int x,int fa){
dml[deep[x]]=max(dml[deep[x]],dis[x]);
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y!=fa&&!vis[y]){
dis[y]=dis[x]+c[i];
get_maxdis(y,x);
}
}
}
void get_deep(int x,int fa){
;M_DEP=max(M_DEP,deep[x]);
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y!=fa&&!vis[y]){
deep[y]=deep[x]+1;
get_deep(y,x);
}
}
}
void work(int x){
rt[++tot]=x;vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(!vis[y]){
root=0;SIZE=size[y];getroot(y,0);
work(root);
}
}
}
void work2(int x){
tot2++;x=rt[tot2];int cnt2=0;vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(!vis[y]){
dis[y]=c[i];
M_DEP=deep[y]=1;get_deep(y,x);
son[++cnt2]=(data){y,M_DEP};
}
}
int last=0;
sort(son+1,son+1+cnt2,cmp);
for(int i=1;i<=cnt2;i++){
get_maxdis(son[i].id,x);
int st=1,ed=0,l=last,r=last;
for(int j=1;j<=son[i].dep;j++){
while(l>=0&&l>=L-j){
while(st<=ed&&ANS[q[ed]]<ANS[l]) ed--;
q[++ed]=l--;
}
for(;r>=0&&r+j>R;r--) while(st<=ed&&q[st]>=r) st++;
if(st<=ed) ans=max(ans,dml[j]+ANS[q[st]]);
}
for(int j=1;j<=son[i].dep;j++) ANS[j]=max(ANS[j],dml[j]),dml[j]=(double)-Inf;
last=max(last,son[i].dep);
}
for(int i=1;i<=last;i++) ANS[i]=(double)-Inf;
if(ans>=0) return;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(!vis[y]){
work2(y);
}
}
}
bool check(double mid){
for(int i=1;i<=cnt;i++) c[i]-=mid;
for(int i=1;i<=n;i++) vis[i]=0,dis[i]=0,deep[i]=0;ans=-Inf;
tot2=0;work2(rt[1]);
for(int i=1;i<=cnt;i++) c[i]+=mid;
return ans>=0;
}
int main(){
n=gi();L=gi();R=gi();
int x,y,z;
for(int i=1;i<n;i++){
x=gi(),y=gi(),z=gi();lnk(x,y,z);
}
for(int i=1;i<=n;i++) dml[i]=ANS[i]=-Inf;
root=0;f[0]=Inf;SIZE=n;getroot(1,0);work(root);
double l=0,r=1000000;
while(r-l>eps){
double mid=(l+r+eps)/2;
if(check(mid))l=mid;
else r=mid-eps;
}
printf("%.3lf",l);
}

bzoj 1758: [Wc2010]重建计划的更多相关文章

  1. bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check

    [Wc2010]重建计划 Time Limit: 40 Sec  Memory Limit: 162 MBSubmit: 4345  Solved: 1054[Submit][Status][Disc ...

  2. BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)

    题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...

  3. BZOJ 1758: [Wc2010]重建计划 [暂时放弃]

    今天晚上思维比较乱,以后再写写吧#include <iostream> #include <cstdio> #include <cstring> #include ...

  4. BZOJ 1758: [Wc2010]重建计划 01分数规划+点分治+单调队列

    code: #include <bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in", ...

  5. BZOJ1758: [Wc2010]重建计划

    题解: 这题我居然做了一星期?... 平均值的极值其实也可以算是一种分数规划,只不过分母上b[i]=1 然后我们就可以二分这个值.类似与 HNOI最小圈 如果没有 链的长度的限制的话,我们直接两遍df ...

  6. 洛谷 P4292 [WC2010]重建计划 解题报告

    P4292 [WC2010]重建计划 题目描述 \(X\)国遭受了地震的重创, 导致全国的交通近乎瘫痪,重建家园的计划迫在眉睫.\(X\)国由\(N\)个城市组成, 重建小组提出,仅需建立\(N-1\ ...

  7. [WC2010]重建计划 长链剖分

    [WC2010]重建计划 LG传送门 又一道长链剖分好题. 这题写点分治的人应该比较多吧,但是我太菜了,只会长链剖分. 如果你还不会长链剖分的基本操作,可以看看我的长链剖分总结. 首先一看求平均值最大 ...

  8. BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)

    题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...

  9. 【bzoj1758】[Wc2010]重建计划

    Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案, ...

随机推荐

  1. java系列视频教程下载

    1.马士兵J2SE基础录屏视频 珍藏版 链接:https://pan.baidu.com/s/1eRMJqkq    密码:qa66 2.spring视频教程 链接:https://pan.baidu ...

  2. 命令模式(Command)

    命令模式(Command) 命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行.这个过程好在,三者相互 ...

  3. 这些 Drawable 的小技巧,你都了解吗?

    一.前言 在 Android 的开发过程中,Drawable 经常会被用到,一般会用 Drawable 为 View 设置一个显示的效果.而在 Android 下,也提供了很多 Drawable 的默 ...

  4. P1040 加分二叉树

    转自:(http://www.cnblogs.com/geek-007/p/7197439.html) 经典例题:加分二叉树(Luogu 1040) 设一个 n 个节点的二叉树 tree 的中序遍历为 ...

  5. 地图开发GIS的应用有哪些?

    GIS的应用领域有哪些? 地理信息系统在最近的30多年内取得了惊人的发展,广泛应用于资源调查.环境评估.灾害预测.国土管理.城市规划.邮电通讯.交通运输.军事公安.水利电力.公共设施管理.农林牧业.统 ...

  6. let 和 const

    let命令 1.let命令只在所在的代码快内有效 { let a = 'hello world' console.log(a) //hello world } console.log(a) //Unc ...

  7. Python3 词汇助手 有道翻译助手 有道导出文件格式转换

    根据有道翻译软件的功能,结合实际用途,基于Python3.6写了一个有道翻译助手软件. 测试文件及源代码已上传至:https://github.com/MMMMMichael/Translation- ...

  8. 掌握sklearn系列——1 学会加载数据

    我们直接看代码: from sklearn import datasets #读取三组数据,前两个用于分类,第三个用于回归 iris = datasets.load_iris() digits = d ...

  9. startup alter.log spfile.ora

    SQL> select * from v$version where rownum=1; BANNER --------------------------------------------- ...

  10. Android Api 检查參数状态Api

    转载请注明出处:http://blog.csdn.net/droyon/article/details/39938677 在进行Android应用程序开发中,android提供了一个非常好的工具类,来 ...