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

数据范围:$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. 如何修改路由器的登录IP地址?

    如何修改路由器的登录IP地址? 因为有多个路由器,为了区分不同路由器,我们可以修改它的登录IP,而且修改后,可以在连接的电脑上直观地知道所连接的是哪一台路由器 买回来的路由器,一般默认的登录地址是19 ...

  2. jquery中innerWidth(),outerWidth(),outerWidth(true)和width()的区别

    jquery中innerWidth(),outerWidth(),outerWidth(true)和width()的区别 var a = 元素本身的宽度: width() = a: innerWidt ...

  3. METAGENOMIC SEQUENCING ANALYSIS WORKFLOW

    Metagenomics is defined as the study of the metagenome, which is total genomic DNA from environmenta ...

  4. HDU 2546 饭卡 (01背包问题)

    题意:中文的吧,飘过~ 析:学过DP的都应该感觉到是动态规划吧,就是一个01背包问题,不同的是,这个题又加入一些新的条件,就是不满5元不能消费,过了5元即使超了也行(这个学校真不错,都可以预支),最后 ...

  5. 阿里Sophix热修复

    阿里巴巴对Android热修复技术已经进行了长达多年的探索. 最开始,是手淘基于Xposed进行了改进,产生了针对Android Dalvik虚拟机运行时的Java Method Hook技术,Dex ...

  6. 一致性哈希算法和Go语言实现

    一致性哈希算法,当我第一次听到这个名字的时候,感觉特别高深.而它往往会和分布式系统相关,准确的说,是分布式缓存. 在Web服务中,缓存是介于数据库和服务端程序之间的一个东西.在网站的业务还不是很大的时 ...

  7. hdu 5033 模拟+单调优化

    http://acm.hdu.edu.cn/showproblem.php?pid=5033 平面上有n个建筑,每个建筑由(xi,hi)表示,m组询问在某一个点能看到天空的视角范围大小. 维护一个凸包 ...

  8. 取得 APP 自己的版本号 (跨 4 个平台)

    http://www.cnblogs.com/onechen/p/3627942.html XE7 源码下载:[原创]取得APP自己的版本号(狠跨4个平台)XE7.zip XE6 源码下载:[原创]取 ...

  9. Python学习-19.Python的Http模块

    模拟 http 请求是比较常见的一种需求,在 Python 中,使用 http 模块操作. import http.client # 创建 Http 连接. http = http.client.HT ...

  10. 在centos docker中安装nvidia驱动

    因为计算需要用到GPU加速, 今天尝试在centos 机器的Docker里安装了GTX980驱动, 记录一下详细安装过程. 首先安装Docker和镜像: sudo yum install docker ...