题意:

给定一棵n个点的树,每条边有权值。
求一条链,这条链包含的边数在L和U之间,且平均边权最大。
N﹤=100000

思路:

做法一:RYZ作业

二分答案再点分治,寻找是否有大于0且边数在L和U之间的链

f[i]为当前子树深度为i的链最大总和,g[i]为前几个深度为i的链最大总和

维护一个下标递增,值递增的单调队列

按子树深度排序一定要加,因为清空与当前子树深度最大值有关,不加的话可能会退化成n^2

改了快一天改不出,还加了迭代,最后发现是分治的时候root打成v,相当于什么都没干……

 var head,vet,next,c,d,size,flag,q1:array[..]of longint;
p:array[..]of longint;
len,h,q2:array[..]of double;
f,g:array[..]of double;
n,i,tot,root,l1,r1,sum,mx,mxdep,x,y,z,tmp,t,w,now,m:longint;
eps,oo,mid:double; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; function max(x,y:longint):longint;
begin
if x>y then exit(x);
exit(y);
end; function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end; procedure add(a,b,c:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
len[tot]:=c;
head[a]:=tot;
end; procedure getroot(u,fa:longint);
var e,v:longint;
begin
size[u]:=; p[u]:=;
e:=head[u];
while e<> do
begin
v:=vet[e];
if (v<>fa)and(flag[v]=) then
begin
getroot(v,u);
size[u]:=size[u]+size[v];
p[u]:=max(p[u],size[v]);
end;
e:=next[e];
end;
p[u]:=max(p[u],sum-p[u]);
if p[u]<p[root] then root:=u;
end; procedure dfs(u,fa,dep:longint;t:double);
var e,v:longint;
begin
if f[dep]<t then f[dep]:=t;
mx:=max(mx,dep);
e:=head[u];
while e<> do
begin
v:=vet[e];
if (v<>fa)and(flag[v]=) then dfs(v,u,dep+,t+len[e]-mid);
e:=next[e];
end; end; procedure ins(k:longint;x:double);
begin
while (w>=t)and(q2[w]<x) do dec(w);
inc(w); q1[w]:=k; q2[w]:=x;
end; procedure del(k:longint);
begin
while (t<=w)and(q1[t]>=k) do inc(t);
end; procedure getdep(u,fa,dep:longint);
var e,v:longint;
begin
e:=head[u];
if dep>d[m] then d[m]:=dep;
while e<> do
begin
v:=vet[e];
if (v<>fa)and(flag[v]=) then getdep(v,u,dep+);
e:=next[e];
end;
end; procedure qsort(l,r:longint);
var i,j,mid:longint;
t:double;
begin
i:=l; j:=r; mid:=d[(l+r)>>];
repeat
while mid>d[i] do inc(i);
while mid<d[j] do dec(j);
if i<=j then
begin
swap(d[i],d[j]);
swap(c[i],c[j]);
t:=h[i]; h[i]:=h[j]; h[j]:=t;
inc(i); dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end; function solve(u:longint;avg:double):double;
var t1,t2,ans,tmp:double;
v,e,i,j:longint;
begin
t1:=avg; t2:=-oo;
m:=;
e:=head[u];
while e<> do
begin
v:=vet[e];
if flag[v]= then
begin
inc(m);
getdep(v,u,);
c[m]:=v; h[m]:=len[e];
end;
e:=next[e];
end;
if m> then qsort(,m);
while t1-t2>eps do
begin
t2:=t1; mid:=t1; ans:=-oo;
mxdep:=; g[]:=;
for j:= to m do
begin
v:=c[j];
mx:=;
dfs(v,u,,h[j]-mid);
t:=; w:=;
for i:=min(mxdep,r1) to l1 do ins(i,g[i]);
for i:=max(,l1-mxdep) to mx do
begin
if l1-i>= then ins(l1-i,g[l1-i]);
del(r1-i+);
if t<=w then
if (f[i]+q2[t])/(q1[t]+i)>ans then
ans:=(f[i]+q2[t])/(q1[t]+i);
end;
mxdep:=max(mxdep,mx);
for i:= to mx do
if f[i]>g[i] then g[i]:=f[i];
for i:= to mx do f[i]:=-oo;
end;
for i:= to mxdep do g[i]:=-oo;
t1:=t1+ans;
end;
flag[u]:=; t2:=t1;
e:=head[u];
while e<> do
begin
v:=vet[e];
if flag[v]= then
begin
root:=; sum:=size[v];
getroot(v,);
tmp:=solve(root,t1);
if tmp>t2 then t2:=tmp;
end;
e:=next[e];
end;
exit(t2); end; begin
assign(input,'bzoj1758.in'); reset(input);
assign(output,'bzoj1758.out'); rewrite(output);
readln(n);
readln(l1,r1);
oo:=1e8;
for i:= to n- do
begin
readln(x,y,z);
add(x,y,z);
add(y,x,z);
end;
p[]:=n+; root:=; sum:=n;
eps:=1e-4;
getroot(,);
for i:= to n do
begin
f[i]:=-oo; g[i]:=-oo;
end;
writeln(solve(root,)::);
close(input);
close(output);
end.

做法2:From https://blog.bill.moe/WC2010-rebuild/

建立一个答案表,顺序是长链剖分的dfs序

长链可以共用答案表,轻儿子暴力合并到父亲所在长链中

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef pair<ll,int>P;
#define N 200010
#define M 200010
#define fi first
#define se second
#define MP make_pair
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1 const ll MOD=1e9+,inv2=(MOD+)/;
double eps=1e-;
int INF=<<;
ll inf=5e13;
int dx[]={-,,,};
int dy[]={,,-,}; double t[N<<];
int head[N],vet[N],len[N],nxt[N],
dep[N],son[N],slen[N],fa[N],id[N],dfn[N],mx[N],top[N],
tot,L,R,tim,n;
double ans,tmp[N]; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} void add(int a,int b,int c)
{
nxt[++tot]=head[a];
vet[tot]=b;
len[tot]=c;
head[a]=tot;
} void build(int l,int r,int p)
{
t[p]=-1e18;
if(l==r)
{
id[l]=p;
return;
}
int mid=(l+r)>>;
build(l,mid,ls);
build(mid+,r,rs);
} void update(int u,double v)
{
int now=id[u];
while(now)
{
t[now]=max(t[now],v);
now>>=;
}
} double query(int l,int r,int x,int y,int p)
{
if(x<=l&&r<=y) return t[p];
int mid=(l+r)>>;
double res=-1e18;
if(x<=mid) res=max(res,query(l,mid,x,y,ls));
if(y>mid) res=max(res,query(mid+,r,x,y,rs));
return res;
} void dfs1(int u,int pre,int d)
{
dep[u]=mx[u]=d;
fa[u]=pre;
int e=head[u];
while(e)
{
int v=vet[e];
if(v!=pre)
{
dfs1(v,u,d+);
if(mx[v]>mx[son[u]])
{
son[u]=v;
slen[u]=len[e];
mx[u]=mx[v];
}
}
e=nxt[e];
}
} void dfs2(int u,int ance)
{
top[u]=ance;
dfn[u]=++tim;
if(son[u]) dfs2(son[u],ance);
int e=head[u];
while(e)
{
int v=vet[e];
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
e=nxt[e];
}
} double ask(int u,int l,int r)
{
l=max(l,);
r=min(r,mx[u]-dep[u]);
if(l>r) return -1e18;
return query(,n,dfn[u]+l,dfn[u]+r,);
} void solve(int u,double d,double mid)
{
update(dfn[u],d);
if(son[u]) solve(son[u],d+slen[u]-mid,mid);
int e=head[u];
while(e)
{
int v=vet[e];
if(v!=fa[u]&&v!=son[u])
{
solve(v,d+len[e]-mid,mid);
rep(j,,mx[v]-dep[v]+)
{
tmp[j]=t[id[dfn[v]+j-]];
ans=max(ans,tmp[j]+ask(u,L-j,R-j)-*d);
}
rep(j,,mx[v]-dep[v]+) update(dfn[u]+j,tmp[j]);
}
e=nxt[e];
}
ans=max(ans,ask(u,L,R)-d);
} int isok(double K)
{
build(,n,);
ans=-1e18;
solve(,,K);
return ans>=-eps;
} int main()
{
n=read(),L=read(),R=read();
tot=;
rep(i,,n-)
{
int x=read(),y=read(),z=read();
add(x,y,z);
add(y,x,z);
}
dfs1(,,);
tim=;
dfs2(,);
double left=,right=1e10;
while(right-left>eps)
{
double mid=(left+right)/;
if(isok(mid)) left=mid;
else right=mid;
}
printf("%.3f\n",left);
return ;
}

【BZOJ1758】重建计划(点分治)的更多相关文章

  1. [BZOJ1758][WC2010]重建计划(点分治+单调队列)

    点分治,对于每个分治中心,考虑求出经过它的符合长度条件的链的最大权值和. 从分治中心dfs下去取出所有链,为了防止两条链属于同一个子树,我们一个子树一个子树地处理. 用s1[i]记录目前分治中心伸下去 ...

  2. [WC2010][BZOJ1758]重建计划-[二分+分数规划+点分治]

    Description 传送门 Solution 看到那个式子,显然想到分数规划...(不然好难呢) 然后二分答案,则每条边的权值设为g(e)-ans.最后要让路径长度在[L,U]范围内的路径权值&g ...

  3. WC2010 BZOJ1758 重建计划_长链剖分

    题目大意: 求长度$\in [L,U]$的路径的最大边权和平均值. 题解 首先二分就不用说了,分数规划大家都懂. 这题有非常显然的点分治做法,但还是借着这个题学一波长链剖分. 其长链剖分本身也没啥,就 ...

  4. P4292 [WC2010]重建计划 点分治+单调队列

    题目描述 题目传送门 分析 看到比值的形式就想到 \(01分数规划\),二分答案 设当前的值为 \(mids\) 如果存在\(\frac{\sum _{e \in S} v(e)}{|S|} \geq ...

  5. 蒟蒻的长链剖分学习笔记(例题:HOTEL加强版、重建计划)

    长链剖分学习笔记 说到树的链剖,大多数人都会首先想到重链剖分.的确,目前重链剖分在OI中有更加多样化的应用,但它大多时候是替代不了长链剖分的. 重链剖分是把size最大的儿子当成重儿子,顾名思义长链剖 ...

  6. 【BZOJ1758】【WC2010】重建计划(点分治,单调队列)

    [BZOJ1758][WC2010]重建计划(点分治,单调队列) 题面 BZOJ 洛谷 Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表 ...

  7. BZOJ1758: [Wc2010]重建计划

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

  8. 「WC2010」重建计划(长链剖分/点分治)

    「WC2010」重建计划(长链剖分/点分治) 题目描述 有一棵大小为 \(n\) 的树,给定 \(L, R\) ,要求找到一条长度在 \([L, R]\) 的路径,并且路径上边权的平均值最大 \(1 ...

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

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

  10. BZOJ 1758 【WC2010】 重建计划

    题目链接:重建计划 这道题现在已经成为一道板子题了…… 这是个非常显然的0-1分数规划,可以二分答案之后树分治判定一下.注意树分治的时候如果使用单调队列,需要把所有儿子预先按最大深度排好序,否则会被扫 ...

随机推荐

  1. 定时清除 /var/log/massage 下的信息脚本文件

    定时清除 /var/log/massage 下的信息脚本 #!/bin/sh #Date: 0:07 #Author: Xiaodong #Mail: 990974238@qq.com #Puncti ...

  2. 在spring data jpa中使用自定义转换器之使用枚举转换

    转载请注明http://www.cnblogs.com/majianming/p/8553217.html 在项目中,经常会出现这样的情况,一个实体的字段名是枚举类型的 我们在把它存放到数据库中是需要 ...

  3. 单例模式及php实现

    单例模式: 单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法. 单例模式的要点有三个:一 ...

  4. php debug/phpstorm调试

    apache+phpstorm调试php代码,修改php.ini配置文件开启调试,没有以下代码加上即可, [XDebug]zend_extension="C:\php\php-7.0.12- ...

  5. JData 整合ArtTemplate的前端框架

    因为项目需要和自己的兴趣,几个月前结合模板解析神速的ArtTemplate,自己写了个框架取名JData,多多指教啊---因为一直没时间写文档,为了能够更方便地使用和避免我把代码忘了,今天抽空把文档写 ...

  6. 阿里云服务器安装ss使用

    下载安装服务器版shadowsocks yum install epel-release yum update yum install python-setuptools m2crypto super ...

  7. Katalon Studio(二) 进阶战の Jenkins集成 analytics.katalon 集成

    本教程只针对Katalon Studio 与CI工具之一Jenkins的集成与脚本集的测试报告可视化简单操作. 1.新建一个job 2.新建一个自由风格的job 3.构建触发器 4.构建Windows ...

  8. swift 语言评价

    杂而不精,一团乱麻!模式乱套,不适合作为一门学习和研究语言. 谢谢 LZ 介绍,看完之后更不想用 Swift 了.从 C++那里抄个 V-Table 来很先进嘛?别跟 C++一样搞什么 STL 就好了 ...

  9. 如何优雅地从CSDN转载文章

    复制粘贴应该是最显而易见的方法,但是不仅会有丢失内容,而且格式也会丢失.要想达到更好的效果,可以从html源码入手. 1.在chrome浏览器中打开要转载的文章,右键选择检查 2.在chrome的右方 ...

  10. VINS-Mono论文笔记(未完)

    这是整篇论文的架构,下面针对每一部分进行自己的详细理解.(数学公式的问题没在博客里面解决,都是论文中的截图,尽可能美观==) 一.测量预处理部分(MEASUREMENT PREPROCESSING) ...