【NOI2013】快餐店 环套树+线段树
题目大意:给你一颗环套树,你要在这棵的边上(包括端点)找一个点,使得离该点最远的点最近。
数据范围:$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】快餐店 环套树+线段树的更多相关文章
- 浅谈树套树(线段树套平衡树)&学习笔记
0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...
- 【BZOJ-3306】树 线段树 + DFS序
3306: 树 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 792 Solved: 262[Submit][Status][Discuss] De ...
- BZOJ_3196_二逼平衡树_(树套树,线段树+Treap)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3196 可以处理区间问题的平衡树. 3196: Tyvj 1730 二逼平衡树 Time Lim ...
- Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6471 Solved: 2697[Su ...
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...
- BZOJ 3685: 普通van Emde Boas树( 线段树 )
建颗权值线段树就行了...连离散化都不用... 没加读入优化就TLE, 加了就A掉了...而且还快了接近1/4.... ---------------------------------------- ...
- LOJ#3043.【ZJOI2019】 线段树 线段树,概率期望
原文链接www.cnblogs.com/zhouzhendong/p/ZJOI2019Day1T2.html 前言 在LOJ交了一下我的代码,发现它比选手机快将近 4 倍. 题解 对于线段树上每一个节 ...
- poj 2155 matrix 二维线段树 线段树套线段树
题意 一个$n*n$矩阵,初始全为0,每次翻转一个子矩阵,然后单点查找 题解 任意一种能维护二维平面的数据结构都可以 我这里写的是二维线段树,因为四分树的写法复杂度可能会退化,因此考虑用树套树实现二维 ...
- cf842D 01字典树|线段树 模板见hdu4825
一般异或问题都可以转换成字典树的问题,,我一开始的想法有点小问题,改一下就好了 下面的代码是逆向建树的,数据量大就不行 /*3 01字典树 根据异或性质,a1!=a2 ==> a1^x1^..^ ...
随机推荐
- 【JAVA】通过HttpURLConnection 上传和下载文件(二)
HttpURLConnection文件上传 HttpURLConnection采用模拟浏览器上传的数据格式,上传给服务器 上传代码如下: package com.util; import java.i ...
- 2018.09.07 bzoj1911: [Apio2010]特别行动队(斜率优化dp)
传送门 斜率优化dp经典题. 题目中说的很清楚,设f[i]表示前i个数分配出的最大值. 那么有: f[i]=max(f[j]+A∗(sum[i]−sum[j])2+B∗(sum[i]−sum[j])+ ...
- py-函数基础
定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 1.减少重复代码2.使程序变的可扩展3.使程序变得易维护 函数参数 形参变量 只有在被调 ...
- 用jQ实现一个简易计算器
HTML和CSS结构: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- Android绘图板的开发
>>继承自View >>使用Canvas绘图 每次View组件上的图形状态数据发生了改变,都应该通知View组件重写调用onDraw(Canvas canvas)方法重绘该组件 ...
- Perf -- Linux下的系统性能调优工具,第 1 部分
Perf 简介 Perf 是用来进行软件性能分析的工具. 通过它,应用程序可以利用 PMU,tracepoint 和内核中的特殊计数器来进行性能统计.它不但可以分析指定应用程序的性能问题 (per t ...
- PAT甲 1012. The Best Rank (25) 2016-09-09 23:09 28人阅读 评论(0) 收藏
1012. The Best Rank (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue To eval ...
- win7系统窗口背景颜色设置为护眼色的方法---打开的任意窗口显示为护眼色,程序眼必备
win7系统窗口背景颜色设置为护眼色的方法 1. 打开"窗口颜色与外观"对话框 方法1:从控制面板开始 控制面板\外观和个性化\个性化\窗口颜色和外观 方法2:桌面上鼠标右键,个性 ...
- Python学习-37.Python中的正则表达式
作为一门现代语言,正则表达式是必不可缺的,在Python中,正则表达式位于re模块. import re 这里不说正则表达式怎样去匹配,例如\d代表数字,^代表开头(也代表非,例如^a-z则不匹配任何 ...
- C# 二维码/条形码入门操作
效果图: 先给之前的群友道个歉,说声不好意思.QRCoder 只支持二维码,没有条形码. 以上demo生成条形码是用 BarcodeLib 这个库,识别是用 zxing,二维码生成用 QRCoder, ...