传送门

注意到答案为这个基环树直径\(/2\)

因为是基环树,所以考虑把环拎出来.如果直径不过环上的边,那么可以在环上每个点下挂的子树内\(dfs\)求得.然后如果过环上的边,那么环上的部分也是一条链,考虑拆环为链,现在问题是一条链,每个点往下延伸若干长度,问最远的距离.每个点往下最长的长度可以随便预处理,然后最长的路径一定是两个点以及往下延伸的路径+在链上两点之间的路径,也可以看成这条长链+前面那个点往下的链-前面链的部分+后面那个点往下的链-后面链的部分,所以可以维护两棵线段树,分别维护 点往下的链-前面链的部分 以及 点往下的链-后面链的部分,然后第一棵树的最大值和第二棵的最大值加长链长度就可以更新答案.然后每次删掉最前面那个点,加到链的最后面,两个线段树分别区间修改即可.

注意如果第一棵树的前缀最大值是最后一个点,那么要用第二棵树最大值+第一棵树到第二棵树最大值前面一位的前缀最大值更新答案

#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define il inline using namespace std;
const LL N=1e5+10,mod=1e9+7;
il LL rd()
{
LL x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int to[N<<1],nt[N<<1],w[N<<1],hd[N],tot=1;
void add(int x,int y,int z)
{
++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;
++tot,to[tot]=x,nt[tot]=hd[y],w[tot]=z,hd[y]=tot;
}
int n,m,st[N][2],tp;
LL cr[N][2],de[N],dp[N];
bool v[N],ic[N];
bool d1(int x,int ffa)
{
if(v[x])
{
while(tp)
{
cr[++m][0]=st[tp][0],cr[m][1]=st[tp][1];
ic[st[tp][0]]=1;
if(st[tp][0]==x) break;
--tp;
}
return 1;
}
v[x]=1,st[++tp][0]=x;
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(y==ffa) continue;
st[tp][1]=w[i];
if(d1(y,x)) return 1;
}
--tp;
return 0;
}
void d2(int x,int ffa)
{
st[++tp][0]=x;
dp[x]=de[x];
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(ic[y]||y==ffa) continue;
de[y]=de[x]+w[i],d2(y,x),dp[x]=max(dp[x],dp[y]);
}
}
#define mid ((l+r)>>1)
struct SegmentTree
{
LL s[N<<3],tg[N<<3];
int lc[N<<3];
void ad(int o,LL x){s[o]+=x,tg[o]+=x;}
void psup(int o){s[o]=max(s[o<<1],s[o<<1|1]),lc[o]=s[o<<1]>=s[o<<1|1]?lc[o<<1]:lc[o<<1|1];}
void psdn(int o){if(tg[o]) ad(o<<1,tg[o]),ad(o<<1|1,tg[o]),tg[o]=0;}
void modif(int o,int l,int r,int ll,int rr,LL x)
{
if(ll<=l&&r<=rr){ad(o,x);return;}
psdn(o);
if(ll<=mid) modif(o<<1,l,mid,ll,rr,x);
if(rr>mid) modif(o<<1|1,mid+1,r,ll,rr,x);
psup(o);
}
void modif(int o,int l,int r,int lx,LL x)
{
if(l==r){ad(o,x);return;}
psdn(o);
if(lx<=mid) modif(o<<1,l,mid,lx,x);
else modif(o<<1|1,mid+1,r,lx,x);
psup(o);
}
LL quer(int o,int l,int r,int ll,int rr,int &lx)
{
if(ll<=l&&r<=rr) {lx=lc[o];return s[o];}
psdn(o);
LL a1=-(1ll<<50),a2=-(1ll<<50);
int l1=0,l2=0;
if(ll<=mid) a1=quer(o<<1,l,mid,ll,rr,l1);
if(rr>mid) a2=quer(o<<1|1,mid+1,r,ll,rr,l2);
psup(o);
lx=a1>=a2?l1:l2;
return max(a1,a2);
}
void bui(int o,int l,int r)
{
if(l==r){lc[o]=l;return;}
bui(o<<1,l,mid),bui(o<<1|1,mid+1,r);
psup(o);
}
}tr1,tr2; int main()
{
n=rd();
for(int i=1;i<=n;++i)
{
int x=rd(),y=rd(),z=rd();
add(x,y,z);
}
d1(1,0);
LL dn=0;
for(int i=1;i<=m;++i)
{
tp=0;
d2(cr[i][0],0);
LL nw=dp[cr[i][0]];
//printf("%lld %lld\n",nw,cr[i][1]);
int x=0;
while(tp)
{
if(de[st[tp][0]]==nw) {x=st[tp][0];break;}
--tp;
}
tp=0;
ic[cr[i][0]]=0;
de[x]=0,d2(x,0);
ic[cr[i][0]]=1;
dn=max(dn,dp[x]);
dp[cr[i][0]]=nw;
}
LL ln=0,ans=1ll<<50;
tr1.bui(1,1,m+m+1),tr2.bui(1,1,m+m+1);
for(int ll=1-m,rr=0;rr<m+m;)
{
if(ll>0) tr1.modif(1,1,m+m+1,ll,rr,cr[ll%m+1][1]),ln-=cr[ll%m+1][1];
++ll;
if(rr>0) ln+=cr[rr%m+1][1],tr2.modif(1,1,m+m+1,max(ll,1),rr,-cr[rr%m+1][1]);
++rr;
tr1.modif(1,1,m+m+1,rr,dp[cr[(rr-1)%m+1][0]]-ln),tr2.modif(1,1,m+m+1,rr,dp[cr[(rr-1)%m+1][0]]);
if(ll>0)
{
int lx=0,ee;
LL dt=ln+tr1.quer(1,1,m+m+1,ll,rr,lx);
if(lx<rr) dt+=tr2.quer(1,1,m+m+1,lx+1,rr,ee);
LL d2=ln+tr2.quer(1,1,m+m+1,ll,rr,lx);
if(lx>ll) d2+=tr1.quer(1,1,m+m+1,ll,lx-1,ee);
ans=min(ans,max(dt,d2));
}
}
ans=max(ans,dn);
printf("%lld.%lld\n",ans>>1,5*(ans&1));
return 0;
}

luogu P1399 [NOI2013]快餐店的更多相关文章

  1. P1399 [NOI2013] 快餐店 方法记录

    原题题面P1399 [NOI2013] 快餐店 题目描述 小 T 打算在城市 C 开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小 T 希望快餐店的地址选在离最 ...

  2. P1399 [NOI2013]快餐店

    传送门 基环树的题当然先考虑树上怎么搞,直接求个直径就完事了 现在多了个环,先把非环上的直径(设为 $ans$)和环上节点 $x$ 到叶子的最大距离(设为 $dis[x]$)求出来 考虑到对于某种最优 ...

  3. bzoj 3242: [Noi2013]快餐店 章鱼图

    3242: [Noi2013]快餐店 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 266  Solved: 140[Submit][Status] ...

  4. bzoj3242 [Noi2013]快餐店

    Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...

  5. 3242: [Noi2013]快餐店 - BZOJ

    Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...

  6. 动态规划:NOI2013 快餐店

    Description 小 T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近 的地方. 快餐店的顾客分布 ...

  7. NOI2013 快餐店

    http://uoj.ac/problem/126 总的来说,还是很容易想的,就是有点恶心. 首先,很明显只有一个环. 我们先找出这个环,给各棵树编号id[i],然后各棵树分别以环上的点为根,求出每个 ...

  8. bzoj 3242: [Noi2013]快餐店

    Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...

  9. BZOJ3242/UOJ126 [Noi2013]快餐店

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

随机推荐

  1. 人工智能之基于Opencv与深度学习的计算机视觉实战课程

    https://www.bilibili.com/video/av66375362 imagewatch:https://blog.csdn.net/iracer/article/details/83 ...

  2. 极验验证码在php5.6.27下不显示

    PHP5.6需要改php.ini 去掉;always_populate_raw_post_data = -1的 :

  3. [THUSC2017]大魔法师:线段树

    分析 在线段树上用\(4 \times 4\)的矩阵打标记. 代码 #include <bits/stdc++.h> #define rin(i,a,b) for(register int ...

  4. spring-servlet.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  5. 网络对抗技术 20165220 Exp7 网络欺诈防范

    网络对抗技术 20165220 Exp7 网络欺诈防范 实验任务 (1)简单应用SET工具建立冒名网站 (1分) (2)ettercap DNS spoof (1分) (3)结合应用两种技术,用DNS ...

  6. Vue 项目构建

    一.初始化项目 1.vue init webpack (fileName) 2.项目名称 3.项目描述 4.项目作者 5.是否依赖 .Vue 文件开发 第一个选项可以不依赖 .Vue 文件开发, 第二 ...

  7. linux fedora原生的快捷键操作

    显示桌面: ctrl+alt+d 运行终端程序: gnome-terminal : 可以自定义快捷键: ctrl+T 等等.

  8. JS中keyup, keypress, keydown以及oninput四个事件的区别

    $email_input.onkeyup=function(event){ // console.log('event handle');//按方向键以及backspce esc有反应 长按字母键也没 ...

  9. Vue知识整理14:组件基础

    组件:可以复用的实例.使用 v-component来实现 2.通过props属性添加相应的属性,并且在模板中渲染 当模板中包含多个组件时,则需要用一个div来包裹起来.如下: 可以将原来的的点击事件, ...

  10. 日常linux命令

    绝对路径用什么符号表示?当前目录.上层目录用什么表示?主目录用什么表示? 切换目录用什么命令?   绝对路径: 如/etc/init.d                当前目录和上层目录: ./  . ...