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/ ...
随机推荐
- BZOJ 3197: [Sdoi2013]assassin 树形DP + 最小费用流 + 树的同构
Description Input Output 其实就是给出两颗树,求一种两种树同构的方式,使得不同颜色个数最少$.$树的重新构建,其实就是指定不同的点为根节点$.$ 好在树的重心有一个重要的性质: ...
- 数据科学20个最好的Python库
Python 在解决数据科学任务和挑战方面继续处于领先地位.去年,我们曾发表一篇博客文章 Top 15 Python Libraries for Data Science in 2017,概述了当时业 ...
- (63)通信协议之一json
1.什么是JSON JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于JavaScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使 ...
- 解决vuex保存的数据刷新页面时清空
参考文章: vuex中store保存的数据,刷新页面会清空 主要解决代码: 1.更改store文件下index文件state的定义 const store = new Vuex.Store({ sta ...
- Oracle-分配用户只读存储过程权限
系统新来了系统运维人员,要求创建数据库账号,只分配对表,视图,存储程序有只读权限 因为表和视图权限接触比较频繁,所以今天花点时间整理下关于存储过程的权限 关于ORACLE账号的权限问题,一般分为两种权 ...
- esLint——规范你的代码(转)
团队协作时,若是团队的代码风格统一,能够大大减少沟通成本. 什么是 ESLint ? ESLint 是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具,它的目标是保证代码 ...
- C++学习一二
为了更深入的学习程序编写,以及进行相关算法的编写.决定每天花点时间学习C++:以下是每天的学习笔记. 一.std代表命名空间,可以用using来省略. 二.std:endl.输出一个换行符,并且“刷新 ...
- 《Effective Java》读书笔记 - 5.泛型
Chapter 5 Generics Item 23: Don't use raw types in new code 虽然你可以把一个List<String>传给一个List类型(raw ...
- Android由出生年月日计算年龄(周岁)
先从String类型的出生日期(“yyyy-MM-dd”)中提取int类型的年.月.日:再计算岁数. 程序如下: /** * 根据出生日期计算年龄的工具类BirthdayToAgeUtil */ pu ...
- Window下PHP环境配置使用Redis总结
什么是Redis? Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value 数据库,并提供多种语言的API.它和Memcached类似,它支持存储的 ...