题目大意:给你一颗环套树,你要在这棵的边上(包括端点)找一个点,使得离该点最远的点最近。

数据范围:$n≤10^5$,边权$≤10^9$。

此题不难看出一种暴力做法,我们依次断开环上的一条边,然后求整颗树的直径,取个$min$就好了,时间复杂度是$O(n^2)$的。

然而显然会$T$,我们考虑一些优秀的做法,我们首先将环拆成链,将链倍长(通用套路),然后将环上的点重新编号一下,设环上点的个数为$m$。

如果我们去掉了这个环,原图会变成森林,对于森林中的每一棵树,我们都先求一下它的直径。

令$D_i$表示以环上第$i$个点为根的子树内,与$i$号点距离最大的点与$i$号点间的距离。

令$S_i$表示环上第$i$个点距离环上第一个点的距离(此处的i可以从$1$取到$2m$)。

那么,对于环上两点$(i,j)$,由$i$为根子树,$j$为根子树,还有i至j的链构成的树的直径为$D_i+D_j-S_i+S_j$。

移项后有$(D_i-S_i)+(D_j+S_j)$。

我们用线段树维护这个东西就可以了,(我的线段树写得有点挫,应该有更高效的编码方法)

 #include<bits/stdc++.h>
#define M 200005
#define L long long
#define INF (1LL<<60)
#define mid ((a[x].l+a[x].r)/2)
using namespace std; struct edge{L u,v,next;}e[M*]={}; L head[M]={},use=;
void add(L x,L y,L z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;} struct node{L l,r;L tag,tag2,mx,mx2,ans;}a[M<<]={};
void build(L x,L l,L r){
a[x].l=l; a[x].r=r; a[x].ans=a[x].mx=a[x].mx2=-INF; if(l==r) return;
build(x<<,l,mid); build(x<<|,mid+,r);
}
void upd(L x,L k){
a[x].tag+=k; a[x].mx+=k;
if(a[x].l!=a[x].r) a[x].ans=max(max(a[x<<].mx+a[x<<|].mx2,a[x<<].mx2+a[x<<|].mx),max(a[x<<].ans,a[x<<|].ans));
}
void upd2(L x,L k){
a[x].tag2+=k; a[x].mx2+=k;
if(a[x].l!=a[x].r) a[x].ans=max(max(a[x<<].mx+a[x<<|].mx2,a[x<<].mx2+a[x<<|].mx),max(a[x<<].ans,a[x<<|].ans));
}
void pushdown(L x){
if(a[x].tag!=) upd(x<<,a[x].tag),upd(x<<|,a[x].tag); a[x].tag=;
if(a[x].tag2!=) upd2(x<<,a[x].tag2),upd2(x<<|,a[x].tag2); a[x].tag2=;
}
void pushup(L x){
a[x].mx=max(a[x<<].mx,a[x<<|].mx);
a[x].mx2=max(a[x<<].mx2,a[x<<|].mx2);
a[x].ans=max(max(a[x<<].mx+a[x<<|].mx2,a[x<<].mx2+a[x<<|].mx),max(a[x<<].ans,a[x<<|].ans));
}
void updata(L x,L l,L r,L k){
if(l<=a[x].l&&a[x].r<=r) return upd(x,k);
pushdown(x);
if(l<=mid) updata(x<<,l,r,k);
if(mid<r) updata(x<<|,l,r,k);
pushup(x);
}
void updata(L x,L k,L val){
if(a[x].l==a[x].r){a[x].tag=; a[x].mx=val; return;}
pushdown(x);
if(k<=mid) updata(x<<,k,val);
else updata(x<<|,k,val);
pushup(x);
}
void updata2(L x,L l,L r,L k){
if(l<=a[x].l&&a[x].r<=r) return upd2(x,k);
pushdown(x);
if(l<=mid) updata2(x<<,l,r,k);
if(mid<r) updata2(x<<|,l,r,k);
pushup(x);
}
void updata2(L x,L k,L val){
if(a[x].l==a[x].r){a[x].tag2=; a[x].mx2=val; return;}
pushdown(x);
if(k<=mid) updata2(x<<,k,val);
else updata2(x<<|,k,val);
pushup(x);
} L cir[M]={},vis[M]={},n,m=; stack<int> st;
bool getcir(L x,L fa){
if(vis[x]){
for(L now=st.top();now!=x;st.pop(),now=st.top()){
cir[++m]=now;
}
cir[++m]=x;
return ;
}
st.push(x); vis[x]=;
for(L i=head[x];i;i=e[i].next) if(e[i].u!=fa){
if(getcir(e[i].u,x)) return ;
}
st.pop();
return ;
} void init(){
scanf("%lld",&n);
for(L i=;i<=n;i++){
L x,y,z; scanf("%lld%lld%lld",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
} L d[M]={},s[M]={},ans=;
L dfs(L x,L fa){
L max1=,max2=;
for(L i=head[x];i;i=e[i].next) if(e[i].u!=fa){
L k=dfs(e[i].u,x)+e[i].v;
if(k>max1) max2=max1,max1=k;
else if(k>max2) max2=k;
}
ans=max(ans,max1+max2);
return max1;
}
void getmax(){
for(L x=;x<=m;x++) cir[x+m]=cir[x];
cir[]=cir[m]; cir[m*+]=cir[];
for(L x=;x<=m;x++){
L max1=,max2=;
for(L i=head[cir[x]];i;i=e[i].next)
if(e[i].u!=cir[x-]&&e[i].u!=cir[x+]){
L k=dfs(e[i].u,cir[x])+e[i].v;
if(k>max1) max2=max1,max1=k;
else if(k>max2) max2=k;
}
ans=max(ans,max1+max2);
d[x]=max1;
} for(L x=;x<=*m;x++){
L u=cir[x];
for(L i=head[u];i;i=e[i].next)
if(e[i].u==cir[x+]) s[x]=e[i].v;
}
} void work(){
L minn=,S=;
for(L i=;i<=m;i++){
S+=s[i-];
updata2(,i,S+d[i]);
minn=max(minn,a[].ans);
updata(,i,d[i]-S);
}
for(L i=;i<=m;i++){
updata(,,m,s[i]);
updata(,i,-INF);
updata2(,,m,-s[i]);
updata2(,i,-INF);
S-=s[i];
S+=s[i+m-];
updata2(,i,S+d[i]);
minn=min(minn,a[].ans);
updata(,i,d[i]-S);
}
ans=max(ans,minn);
} main(){
init();
getcir(,);
build(,,m);
getmax();
work();
double hh=ans; hh/=;
printf("%.1lf\n",hh);
}

【NOI2013】快餐店 环套树+线段树的更多相关文章

  1. 浅谈树套树(线段树套平衡树)&学习笔记

    0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...

  2. 【BZOJ-3306】树 线段树 + DFS序

    3306: 树 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 792  Solved: 262[Submit][Status][Discuss] De ...

  3. BZOJ_3196_二逼平衡树_(树套树,线段树+Treap)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3196 可以处理区间问题的平衡树. 3196: Tyvj 1730 二逼平衡树 Time Lim ...

  4. Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6471  Solved: 2697[Su ...

  5. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  6. BZOJ 3685: 普通van Emde Boas树( 线段树 )

    建颗权值线段树就行了...连离散化都不用... 没加读入优化就TLE, 加了就A掉了...而且还快了接近1/4.... ---------------------------------------- ...

  7. LOJ#3043.【ZJOI2019】 线段树 线段树,概率期望

    原文链接www.cnblogs.com/zhouzhendong/p/ZJOI2019Day1T2.html 前言 在LOJ交了一下我的代码,发现它比选手机快将近 4 倍. 题解 对于线段树上每一个节 ...

  8. poj 2155 matrix 二维线段树 线段树套线段树

    题意 一个$n*n$矩阵,初始全为0,每次翻转一个子矩阵,然后单点查找 题解 任意一种能维护二维平面的数据结构都可以 我这里写的是二维线段树,因为四分树的写法复杂度可能会退化,因此考虑用树套树实现二维 ...

  9. cf842D 01字典树|线段树 模板见hdu4825

    一般异或问题都可以转换成字典树的问题,,我一开始的想法有点小问题,改一下就好了 下面的代码是逆向建树的,数据量大就不行 /*3 01字典树 根据异或性质,a1!=a2 ==> a1^x1^..^ ...

随机推荐

  1. td里的英文字母不会自动换行的问题

    今天发现一个问题,限制了TD的宽度之后,汉字会自动换行,但是英文却不会,在网上搜索一下,发现在TD里面加上style='word-break:break-all'这个样式之后,换行成功 <tab ...

  2. java利用递归实现汉诺塔算法

    package 汉诺塔; //引入Scanner包,用于用户输入 import java.util.Scanner; public class 汉诺塔算法 { public static void m ...

  3. 2018.07.03 POJ 2318 TOYS(二分+简单计算几何)

    TOYS Time Limit: 2000MS Memory Limit: 65536K Description Calculate the number of toys that land in e ...

  4. Django入门指南-第8章:第一个测试用例(完结)

    python manage.py test python manage.py test --verbosity=2 # boards/tests.py from django.core.urlreso ...

  5. oracle11g 导出空表

    --对已存在的表 执行如下 ,要经过统计分析后 num_rows=0 才准确select 'alter table '||table_name||' allocate extent;' from us ...

  6. php学习之路-笔记分享20150327

    由于公司需要,不得已是php也学习并用了段时间做了两个项目,现也分享出笔记.需要源文档的留下邮箱,.

  7. JavaLogin小框架制作【精品博客】

    做一个小登录接口方法,让用户传入用户名,密码,就可以知道登录的结果信息,并以接口监听的方式控制. 先看客户端执行效果: 输入正确: 输入错误: 模拟客户端使用登录小框架: package com.de ...

  8. Mina Session

    Chapter 4 - Session The Session is at the heart of MINA : every time a client connects to the server ...

  9. bootstrap实现左侧图片右侧文字布局

    效果图 代码 通过class="media-left"来控制相对位置 <!DOCTYPE html> <html> <head lang=" ...

  10. NLayerAppV3-Distributed Service Layer(分布式服务层)

    回顾:NLayerAppV3是一个使用.net 2.1实现的经典DDD的分层架构的项目. NLayerAppV3是在NLayerAppV2的基础上,使用.net core2.1进行重新构建的:它包含了 ...