luogu P1399 [NOI2013]快餐店
注意到答案为这个基环树直径\(/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]快餐店的更多相关文章
- P1399 [NOI2013] 快餐店 方法记录
原题题面P1399 [NOI2013] 快餐店 题目描述 小 T 打算在城市 C 开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小 T 希望快餐店的地址选在离最 ...
- P1399 [NOI2013]快餐店
传送门 基环树的题当然先考虑树上怎么搞,直接求个直径就完事了 现在多了个环,先把非环上的直径(设为 $ans$)和环上节点 $x$ 到叶子的最大距离(设为 $dis[x]$)求出来 考虑到对于某种最优 ...
- bzoj 3242: [Noi2013]快餐店 章鱼图
3242: [Noi2013]快餐店 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 266 Solved: 140[Submit][Status] ...
- bzoj3242 [Noi2013]快餐店
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- 3242: [Noi2013]快餐店 - BZOJ
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- 动态规划:NOI2013 快餐店
Description 小 T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近 的地方. 快餐店的顾客分布 ...
- NOI2013 快餐店
http://uoj.ac/problem/126 总的来说,还是很容易想的,就是有点恶心. 首先,很明显只有一个环. 我们先找出这个环,给各棵树编号id[i],然后各棵树分别以环上的点为根,求出每个 ...
- bzoj 3242: [Noi2013]快餐店
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- BZOJ3242/UOJ126 [Noi2013]快餐店
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
随机推荐
- javaweb上传大文件的问题
总结一下大文件分片上传和断点续传的问题.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件 ...
- 【gym102394A】Artful Paintings(差分约束系统,二分)
题意:给定一个长为n的序列,每个位置可以选择取或不取,要求构造方案使得: 1.对于前M1个约束,区间[L,R]内取的数量必须严格不少于K 2.对于后M2个约束,区间[L,R]外取的数量必须严格不少于K ...
- 基于OpenCV/TensorFlow的手写MNIST文字匹配
手写文字具有哪些统一特征?用ML和SVM是如何做到的? 检测 特征匹配 文字识别 毕竟汉语言文字奇形怪状,很不好辨认,尤其是手写体,跟英文字母不同. MNIST一共有哪些库 现实环境更是复杂 有时还只 ...
- Scrapy终端(Scrapy shell)
1.介绍文档:http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/shell.html# 2.终端的启用方式:scrapy shell url u ...
- json 的简单应用
今天做爬虫时的一点盲区 :字符串, 字典,写到同一个文件中.难以利用!比如这样的数据:str = “hi,budy. i like 52pojie!”dirt = {“陈墨”:["男&quo ...
- 系统性能信息模块--psutil
#安装psutil模块#pip install psutil -i https://pypi.doubanio.com/simple #导入psutil模块import psutilimport da ...
- Spring的Aop理解
主要作用:解决代码复用,避免重复性编写代码. 比较典型的场景:日志打印,权限验证,事务处理 参考网址为:http://moon-walker.iteye.com/blog/2381532 spring ...
- 在vi vim中使用正则表达式与 普通perl正则的区别?
参考这篇文章很好 vim中的正则表达式常用的命令有种, 即搜索和替换 /: 搜索 :s 替换 在vim中的正则表达式和perl编程的正则表达式还是有区别的: 正则表达式中的内容包括: 字面字符... ...
- 刃边法计算MTF(ESF、LSF、PSF)
MTF 调制传递函数 评价一个成像系统目前主流的办法主要有三种TV line检测,MTF检测,和SFR检测. MTF是Modulation Transfer Function的英文简称,中文为调制传递 ...
- Delphi XE2 之 FireMonkey 入门(43) - 控件基础: TStringGrid、TGrid
Delphi XE2 之 FireMonkey 入门(43) - 控件基础: TStringGrid.TGrid TStringGrid.TGrid 都是从 TCustomGrid 继承; 区别有:1 ...