[CF1192B]动态直径
题意
给一棵固定形态的树,边有边权,每次修改一条边权,在线求出修改后树的直径。
思考
写出树的全dfs序。生成方式为:每当一个点进栈或入栈时,记录它的编号。
考虑这个dfs序上两点之间的距离。设某个节点在dfs序中第一次出现的位置为$where_i$,第i个位置的节点为$what_i$两个点分别为u和v。可以发现,在dfs上,u和v之间一堆会包含它们的lca,则:
$$dis_{u,v}=max_{where_u \leq x \leq where_v}{\{dep_u+dep_v-2*dep_{what_x}\}}$$
树的直径即为上述表达式的最大值。
考虑到直径的形式为u-lca-v的形式,我们可以在dfs序上看成是L、M、R的这三部分组成,其中L和R要尽可能大,M要尽可能小(代码中先加了符号,所以还是最大的)。考虑线段树,维护当前区间的最大值、M、LM、MR和LMR,最后的答案即为线段树根节点的LMR。不难证明,可以进行如下合并:
$val=max{\{val_l,val_r\}}$
$M=max{\{M_l,M_r\}}$(取了负号)
$LM=max{\{LM_l,LM_r,val_l+M_r\}}$
$MR=max{\{RM_l,RM_r,M_l+val_r\}}$
$LMR=max{\{LMR_l,LMR_r,LM_l+val_r,val_l+RM_r\}}$
对于修改操作,相当于是区间修改,直接打标记即可。
时间复杂度:$O(n+qlogn)$
代码
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const int maxn=1E5+;
typedef long long int ll;
int n,m;
int size=,head[maxn*];
int dfn,dfnFirst[maxn],dfnLast[maxn],what[maxn*],fa[maxn];
ll lastans,weight[maxn],dep[maxn];
ll val[maxn*],M[maxn*],LM[maxn*],MR[maxn*],LMR[maxn*],tag[maxn*];
struct edge
{
int to,next;
ll w;
}E[maxn*];
inline void addE(int u,int v,ll w)
{
E[++size].to=v;
E[size].next=head[u];
E[size].w=w;
head[u]=size;
}
void dfs(int u,int F,ll d)
{
what[dfnFirst[u]=++dfn]=u;
dep[u]=d;
fa[u]=F;
for(int i=head[u];i;i=E[i].next)
{
int v=E[i].to;
if(v==F)
continue;
weight[v]=E[i].w;
dfs(v,u,d+E[i].w);
what[++dfn]=u;
}
dfnLast[u]=dfn;
}
inline void pushdown(int l,int r,int num)
{
val[num]+=tag[num];
M[num]-=tag[num]*;
LM[num]-=tag[num];
MR[num]-=tag[num];
if(l!=r)
tag[num<<]+=tag[num],tag[num<<|]+=tag[num];
tag[num]=;
}
inline void update(int l,int r,int num)
{
if(l==r)
return;
val[num]=max(val[num<<],val[num<<|]);
M[num]=max(M[num<<],M[num<<|]);
LM[num]=max(max(LM[num<<],LM[num<<|]),val[num<<]+M[num<<|]);
MR[num]=max(max(MR[num<<],MR[num<<|]),M[num<<]+val[num<<|]);
LMR[num]=max(max(LMR[num<<],LMR[num<<|]),max(LM[num<<]+val[num<<|],val[num<<]+MR[num<<|]));
}
void build(int l,int r,int num)
{
if(l==r)
{
int pos=what[l];
val[num]=dep[pos];
M[num]=-*dep[pos];
LM[num]=MR[num]=-dep[pos];
return;
}
int mid=(l+r)>>;
build(l,mid,num<<),build(mid+,r,num<<|);
update(l,r,num);
}
void add(int L,int R,int l,int r,ll x,int num)
{
if(L<=l&&r<=R)
{
tag[num]+=x;
pushdown(l,r,num);
return;
}
pushdown(l,r,num);
int mid=(l+r)>>;
if(R<=mid)
add(L,R,l,mid,x,num<<);
else if(mid<L)
add(L,R,mid+,r,x,num<<|);
else
add(L,R,l,mid,x,num<<),add(L,R,mid+,r,x,num<<|);
pushdown(l,mid,num<<);
pushdown(mid+,r,num<<|);
update(l,r,num);
}
int main()
{
ios::sync_with_stdio(false);
ll W;
cin>>n>>m>>W;
for(int i=;i<=n;++i)
{
int x,y;
ll z;
cin>>x>>y>>z;
addE(x,y,z);
addE(y,x,z);
}
dfs(,,);
build(,*n-,);
while(m--)
{
ll x,y;
cin>>x>>y;
x=(x+lastans)%(n-)+;
y=(y+lastans)%W;
if(fa[E[x<<].to]==E[x<<|].to)
x=E[x<<].to;
else
x=E[x<<|].to;
add(dfnFirst[x],dfnLast[x],,*n-,y-weight[x],);
weight[x]=y;
lastans=LMR[];
cout<<lastans<<endl;
}
return ;
}
[CF1192B]动态直径的更多相关文章
- 2019 ICPC上海网络赛 A 题 Lightning Routing I (动态维护树的直径)
题目: 给定一棵树, 带边权. 现在有2种操作: 1.修改第i条边的权值. 2.询问u到其他一个任意点的最大距离是多少. 题解: 树的直径可以通过两次 dfs() 的方法求得.换句话说,到任意点最远的 ...
- 「校内训练 2019-04-23」越野赛车问题 动态dp+树的直径
题目传送门 http://192.168.21.187/problem/1236 http://47.100.137.146/problem/1236 题解 题目中要求的显然是那个状态下的直径嘛. 所 ...
- iOS 实现脉冲雷达以及动态增减元素 By Swift-感谢分享
Swift经过Xcode6 Beta4一版更新后,基本上已经可以作为生产工具了,虽然有一些地方和ObjC比起来要“落后”一些,但也无伤大雅.这里就用Xcode6 Beta4+iOS SDK 8.0开发 ...
- #6145. 「2017 山东三轮集训 Day7」Easy 动态点分治
\(\color{#0066ff}{题目描述}\) JOHNKRAM 最近在参加 C_SUNSHINE 举办的聚会. C 国一共有 n 座城市,这些城市由 n−1 条无向道路连接.任意两座城市之间有且 ...
- 【BZOJ1095】[ZJOI2007]Hide 捉迷藏 动态树分治+堆
[BZOJ1095][ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉 ...
- [LOJ#121]动态图连通性
[LOJ#121]动态图连通性 试题描述 这是一道模板题. 你要维护一张无向简单图.你被要求加入删除一条边及查询两个点是否连通. 0:加入一条边.保证它不存在. 1:删除一条边.保证它存在. 2:查询 ...
- 0x63树的直径与最近公共祖先
凉 bzoj1999 先把树的直径求出来,从左往右枚举,对于当前位置i,找到满足限制并且最远的点j,当前位置最大值就是max(i~j区间内除直径外的子树路径长度最大值,1~i的长度,j~n的长度) 然 ...
- 小程序开发笔记【五】---基于LBS附近动态查询
实现思路 : 获取用户当前位置经纬度坐标 查询动态时将经纬度坐标传给后台 后端通过sql语句计算经纬度坐标之间的距离 // 附近20公里发的动态 按时间排序 let sql = `SELECT * , ...
- 2019ICPC上海网络赛 A Lightning Routing I 点分树(动态点分治)+线段树
题意 给一颗带边权的树,有两种操作 \(C~e_i~w_i\),将第\(e_i\)条边的边权改为\(w_i\). \(Q~v_i\),询问距\(v_i\)点最远的点的距离. 分析 官方题解做法:动态维 ...
随机推荐
- linux中inode的理解
一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统 ...
- Dubbo-本地Bean测试
Dubbo本地测试API的Bean 一.建立一个测试类文件 二.测试API // 自己要测试的API public static final XxApi xxApi; 三.注入Bean static ...
- javascript 闭包的理解(一)
过很多谈如何理解闭包的方法,但大多数文章,都是照抄或者解释<Javascript高级程序设计(第三版)>对于闭包的讲解,甚至例程都不约而同的引用高程三181页‘闭包与变量’一节的那个“返回 ...
- SQL Server内连接、左外连接、右外连接、完全连接、交叉lianjie
数据准备: create table T1( A ) not null, B ) not null, C tinyint not null ); create table T2( B ) not nu ...
- 一篇文章带你了解 ZooKeeper 架构
上一篇文章,我们讲解了 ZooKeeper 入门知识,这篇文章主要讲解下 ZooKeeper 的架构,理解 ZooKeeper 的架构可以帮助我们更好地设计协同服务. 首先我们来看下 ZooKeepe ...
- Django 中配置MySQL数据库
在Django的项目中会默认使用sqlite的数据库 配置MySQL需要在setting.py 里加入以下设置: 配置数据库 DATABASES = { 'default': { 'ENGINE': ...
- flask迁移数据库时报错:Target database is not up的解决方案
在flask中进行数据库迁移时报错,报错信息为"Target database is not up",解决方案如下 找到alembic的最新版本号,找到文件夹migrate下的最新 ...
- 洛谷$P4322\ [JSOI2016]$最佳团体 二分+$dp$
正解:二分+$dp$ 解题报告: 传送门$QwQ$ 这题长得好套路嗷,,,就一看就看出来是个$01$分数规划+树形$dp$嘛$QwQ$. 考虑现在二分的值为$mid$,若$mid\leq as$,则有 ...
- pyspider遇到的第一个坑:Active Tasks成功,Results无内容
#!/usr/bin/env python# -*- encoding: utf-8 -*-# Created on 2020-01-04 16:30:27# Project: HomeWork fr ...
- Ubuntu 18.04 + ROS Melodic + TurtleBot3仿真
1. 下载安装包 官网地址: http://wiki.ros.org/action/show/Robots/TurtleBot?action=show&redirect=TurtleBot 所 ...