传送门

注意到答案为这个基环树直径\(/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. PHP大文件分片上传断点续传实例源码

    1.使用PHP的创始人 Rasmus Lerdorf 写的APC扩展模块来实现(http://pecl.php.net/package/apc) APC实现方法: 安装APC,参照官方文档安装,可以使 ...

  2. js怎么上传文件夹

    1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通 ...

  3. 浅谈BSGS(大步小步)及其扩展

    用途: 一般用来求\(a^x\equiv b\,\,(mod\,p)\)的最小正整数解,其中gcd(a,p)=1 设\(u=\lceil sqrt(p)\rceil\),则式子可以转化为\(a^{iu ...

  4. Spring Boot教程(三)消费Restful的web服务

    构架工程 创建一个springboot工程,去消费RESTFUL的服务.这个服务是 http:///gturnquist-quoters.cfapps.io/api/random ,它会随机返回Jso ...

  5. NABCD分析——生活日历

    N(Need)需求 本软件的主体为日历.如今人们的生活趋于现代化,大家主要通过手机来查看日期,但我们每一天都有想要做或未完成的事情,也存在对自己有特殊意义的日子.每天人们都会有或大或小的支出与收入,想 ...

  6. es之主分片和复制分片的交互过程

    1:索引(创建或者删除)一个文档 首先:发送一个索引或者删除的请求给node1 其次:node1接收到请求之后,会根据请求中携带的参数“文档id”判断出该文档应该存储在具体哪一个shard中 shar ...

  7. 实现mypwd(选做)

    实现mypwd(选做) 任务清单 1 学习pwd命令 2 研究pwd实现需要的系统调用(man -k; grep),写出伪代码 3 实现mypwd 4 测试mypwd (一)pwd命令的学习 1.pw ...

  8. 复选框checked 选中后不显示打钩

    复选框checked 选中后不显示打钩 checkbox属性checked="checked"已有,但复选框却不显示打钩的原因   复选框绑定了click事件,点一次选中,再点击取 ...

  9. p1848 [USACO12OPEN]书架Bookshelf

    分析 单调队列优化dp即可 正确性显然,详见代码 代码 #include<bits/stdc++.h> using namespace std; #define int long long ...

  10. 文件的权利和sudoers中规定的权限哪个更大?

    文件的权利和sudoers中规定的权限哪个更大? 当然是文件的权限更大!!! 这也是linux的 更安全的根本所在! 就是它的每一个文件都有严格的 rwxr--r-- 权限规定. 只有文件权限规定了的 ...