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.util.concurrent 包源码阅读》18 Exchanger

    Exchanger可以看做双向数据传输的SynchronousQueue,即没有生产者和消费者之分,任意两个线程都可以交换数据. 在JDK5中Exchanger被设计成一个容量为1的容器,存放一个等待 ...

  2. 浅谈IM(InstantMessaging) 即时通讯/实时传讯【理论篇】

        一.IM简要概述 IM InstantMessaging(即时通讯,实时传讯)的缩写是IM,互动百科大致解释是一种可以让使用者在网络上建立某种私人聊天(chatroom)的实时通讯服务. 大部 ...

  3. Dashboard集群

    #Dashboard集群 openstack pike 部署 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html ##.Dashboard集群 #####在 ...

  4. 逆向实用干货分享,Hook技术第二讲,之虚表HOOK

    逆向实用干货分享,Hook技术第二讲,之虚表HOOK 正好昨天讲到认识C++中虚表指针,以及虚表位置在反汇编中的表达方式,这里就说一下我们的新技术,虚表HOOK 昨天的博客链接: http://www ...

  5. HDU 1754 线段树 单点跟新 HDU 1166 敌兵布阵 线段树 区间求和

    I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  6. 基于TCP协议的socket编程

    什么是socket Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面, ...

  7. linux shell中单引号、双引号和没有引号的区别

    单引号: 可以说是所见即所得:即将单引号的内的内容原样输出,或者描述为单引号里面看到的是什么就会输出什么. 双引号: 把双引号内的内容输出出来:如果内容中有命令.变量等,会先把变量.命令解析出结果,然 ...

  8. win10 mysql详尽安装教程

    我的电脑系统是win10 64位系统 我安装mysql不下5次,装好了又卸,卸了又装,看了老多篇文章和博客,非常感谢博主的无私帮助,以下是这些博主的文章: https://www.cnblogs.co ...

  9. 简陋的斗地主,js实现

    最近闲了两天没事做,用js写了个斗地主,练习练习.代码和功能都很简陋,还有bug,咋只是聊聊自己的思路. 这里说说斗地主主要包含的功能:洗牌,发牌,玩家出牌.电脑出牌,出牌规则的验证,输赢啥的没有判断 ...

  10. And【sql语句之为何用and一个字段两个值得不到表中的数据】

    一.[一个表的一个字段的多个条件用and连接] 用and是查不到值的, and是多个条件同时成立, 也就是一个字段是不能同时等于两个值的. '; 二[相同两个表的两个相同字段的查询用and连接] '; ...