题意:

给定一棵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. Web自动化测试框架-PO模式

    Web自动化测试框架(WebTestFramework)是基于Selenium框架且采用PageObject设计模式进行二次开发形成的框架. 一.适用范围:传统Web功能自动化测试.H5功能自动化测试 ...

  2. 初学Ajax

    AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术. AJAX = 异步 JavaScript和 ...

  3. C# 判断是否移动设备

    /// <summary> /// 判断是否移动设备. /// </summary> /// <returns></returns> public st ...

  4. js 宿主对象的属性和方法总结

    (1)属性:       //height,width;           a=document.documentElement.clientHeight;           //文档可视高度,由 ...

  5. 平板&Safari 开发tips

    css: *{ margin: 0; padding: 0;  /* 禁止用户点选网页内容 */ -webkit-touch-callout:none; -webkit-user-select:non ...

  6. 10.3 Implementing pointers and objects and 10.4 Representing rooted trees

    Algorithms 10.3 Implementing pointers and  objects  and 10.4 Representing rooted trees Allocating an ...

  7. table鼠标滑过变颜色

    table鼠标滑过变颜色 添加 table tr:hover{background-color: #eee;} 设置鼠标滑过行背景变色,重新刷新浏览器页面.  一般设置灰色,eee

  8. CREATE CAST - 定义一个用户定义的转换

    SYNOPSIS CREATE CAST (sourcetype AS targettype) WITH FUNCTION funcname (argtype) [ AS ASSIGNMENT | A ...

  9. vue工程化:返回顶部和底部的动画效果

    . <template> <div> <div class="scroll" :class="{show:isActive}"&g ...

  10. powerdesigner连接MySQL数据库时出现Non SQL Error : Could not load class com.mysql.jdbc.Driver

    Non SQL Error : Could not load class com.mysql.jdbc.Driver 这是因为powerdesigner 无法找到驱动所产生的 解决办法是:配置系统的c ...