题目:

给定一棵树, 带边权。

现在有2种操作:

1.修改第i条边的权值。

2.询问u到其他一个任意点的最大距离是多少。

题解:

树的直径可以通过两次 dfs() 的方法求得。换句话说,到任意点最远的点,一定是直径的某个端点(反证法)。

• 因此原问题转化为动态维护直径,然后再支持询问两个点的距离,后者可以 dfs 序 + lca + 树状数组。

参考代码:

#include<bits/stdc++.h>
#define lowbit(x) (x&-x)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mkp make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=;
const int INF=<<;
const int maxn=1e5+;
struct Edge{
int u,v,w;
} eg[maxn];
vector<pii> edge[maxn];
int n,q,tin[maxn],tout[maxn],rid[maxn],tot; namespace hld{
//树状数组
struct BIT{
ll a[maxn];
inline void update(int i,int x)
{
while(i<=n)
a[i]+=x,i+=lowbit(i);
}
inline void update(int l,int r,int x)
{
update(l,x); update(r+,-x);
}
inline ll query(int i)
{
ll res=;
while(i) res+=a[i],i-=lowbit(i);
return res;
}
} bit;
//树链剖分
int siz[maxn],dep[maxn],fa[maxn],son[maxn],top[maxn];
void dfs(int u,int f)
{
tin[u]=++tot; rid[tot]=u;
dep[u]=dep[f]+; fa[u]=f; siz[u]=; son[u]=;
int m=-;
for(auto&x:edge[u])
{
int v=x.first;
if(v==f) continue;
dfs(v,u);
bit.update(tin[v],tout[v],x.second);//节点到根的距离
siz[u]+=siz[v];
if(siz[v]>m) son[u]=v,m=siz[v];
}
tout[u]=tot;
}
void dfs(int u,int f,int tp)
{
top[u]=tp;
if(!son[u]) return;
dfs(son[u],u,tp);
for(auto&x:edge[u])
{
int v=x.first;
if(v==f||v==son[u]) continue;
dfs(v,u,v);
}
}
void build() //树链剖分
{
dfs(,);dfs(,,);
}
int qlca(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
ll qdis(int u,int v)
{
ll r=bit.query(tin[u])+bit.query(tin[v]);
int l=qlca(u,v);
return r-2ll*bit.query(tin[l]);
}
}
using hld::qdis;
//线段树+树状数组动态维护树直径
struct Node{
int u,v;
ll d;
} tr[maxn<<];
void pushup(int rt)
{
tr[rt]=tr[rt<<].d>tr[rt<<|].d ? tr[rt<<]:tr[rt<<|];
int x=tr[rt<<].u,y=tr[rt<<].v;
int u=tr[rt<<|].u,v=tr[rt<<|].v;
ll tot;
if((tot=qdis(x,u))>tr[rt].d) tr[rt]=(Node){x,u,tot};
if((tot=qdis(x,v))>tr[rt].d) tr[rt]=(Node){x,v,tot};
if((tot=qdis(y,u))>tr[rt].d) tr[rt]=(Node){y,u,tot};
if((tot=qdis(y,v))>tr[rt].d) tr[rt]=(Node){y,v,tot};
}
void build(int l,int r,int rt)
{
if(l==r)
{
int u=rid[l];
tr[rt]=(Node){u,u,};
return ;
}
int m=(l+r)/;
build(lson); build(rson);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt)
{
if(L<=l && r<=R) return ;
int m=(l+r)/;
if(L<=m) update(L,R,lson);
if(R>m) update(L,R,rson);
pushup(rt);
} int main()
{
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d%d",&eg[i].u,&eg[i].v,&eg[i].w);
edge[eg[i].u].push_back({eg[i].v,eg[i].w});
edge[eg[i].v].push_back({eg[i].u,eg[i].w});
}
hld::build(); //树链剖分
build(,n,); scanf("%d",&q);
char op[];
int e,v,w;
for(int i=;i<=q;++i)
{
scanf("%s",op);
if(op[]=='C')
{
scanf("%d%d",&e,&w);
int u=eg[e].u,v=eg[e].v,ww=eg[e].w;
if(hld::fa[v]!=u) swap(u,v);
hld::bit.update(tin[v],tout[v],w-ww);
eg[e].w=w;
update(tin[v],tout[v],,n,);
}
else if(op[]=='Q')
{
scanf("%d",&v);
int x=tr[].u,y=tr[].v;
printf("%lld\n",max(qdis(x,v),qdis(y,v)));
}
}
return ;
}

2019 ICPC上海网络赛 A 题 Lightning Routing I (动态维护树的直径)的更多相关文章

  1. Peekaboo(2019年上海网络赛K题+圆上整点)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 你的位置在\(O(0,0)\),\(A\)的位置为\((x_1,y_1)\),\(B\)的位置为\((x_2,y_2)\),现在已知\(a=O ...

  2. 2019 ICPC南昌网络赛 B题

    英雄灭火问题忽略了一点丫 一个超级源点的事情,需要考虑周全丫 2 #include<cstdio> #include<cstring> #include<queue> ...

  3. 2019 ICPC南京网络赛 F题 Greedy Sequence(贪心+递推)

    计蒜客题目链接:https://nanti.jisuanke.com/t/41303 题目:给你一个序列a,你可以从其中选取元素,构建n个串,每个串的长度为n,构造的si串要满足以下条件, 1. si ...

  4. 2019 ICPC 南昌网络赛

    2019 ICPC 南昌网络赛 比赛时间:2019.9.8 比赛链接:The 2019 Asia Nanchang First Round Online Programming Contest 总结 ...

  5. 2019 ICPC 上海区域赛总结

    2019上海区域赛现场赛总结 补题情况(以下通过率为牛客提交): 题号 标题 已通过代码 通过率 我的状态 A Mr. Panda and Dominoes 点击查看 5/29 未通过 B Prefi ...

  6. Magic Master(2019年南昌网络赛E题+约瑟夫环)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 初始时你有\(n\)张牌(按顺序摆放),每一次操作你将顶端的牌拿出,然后按顺序将上面的\(m\)张牌放到底部. 思路 首先我们发下拿走\(1\ ...

  7. 计蒜客 2019南昌邀请网络赛J Distance on the tree(主席树)题解

    题意:给出一棵树,给出每条边的权值,现在给出m个询问,要你每次输出u~v的最短路径中,边权 <= k 的边有几条 思路:当时网络赛的时候没学过主席树,现在补上.先树上建主席树,然后把边权交给子节 ...

  8. 2019上海网络赛B题(差分 + 离散化 or 差分 + 思维)

    这题.....队里都没怎么训练差分,导致败北...写了一堆线段树嘤嘤嘤,到最后也是超时,比赛结束后看到了差分的思想于是就去学了一手. 其实了解差分思想的一眼就能看出来是差分了.但是如果对n差分的话很明 ...

  9. 2019年icpc上海网络赛 B Light bulbs (分块、差分)

    https://nanti.jisuanke.com/t/41399 题目大意: 有n个灯,m次操作,每次修改[l,r]内的灯,(off - on ,on - off),问最后有几盏灯亮着. 换种说法 ...

随机推荐

  1. egret编译速度慢解决方法

    egret编译速度慢解决方法 直接用增量更新egret run -a 每次改完代码 保存都会自动编译

  2. python机器学习——逻辑回归

    我们知道感知器算法对于不能完全线性分割的数据是无能为力的,在这一篇将会介绍另一种非常有效的二分类模型--逻辑回归.在分类任务中,它被广泛使用 逻辑回归是一个分类模型,在实现之前我们先介绍几个概念: 几 ...

  3. [TCP/IP] 学习TCP/IP协议的笔记

    1.我看的视频是https://www.bilibili.com/video/av10610680?from=search&seid=1733008388243131444这位大大的视频讲解. ...

  4. lqb 基础练习 闰年判断

    基础练习 闰年判断 时间限制:1.0s   内存限制:256.0MB     问题描述 给定一个年份,判断这一年是不是闰年. 当以下情况之一满足时,这一年是闰年: 1. 年份是4的倍数而不是100的倍 ...

  5. nyoj 266-字符串逆序输出 (isdigit(), geline(cin, my_string))

    266-字符串逆序输出 内存限制:64MB 时间限制:3000ms 特判: No 通过数:15 提交数:18 难度:0 题目描述: 给定一行字符,逆序输出此行(空格.数字不输出) 输入描述: 第一行是 ...

  6. SQL Server设计三范式

    第一范式(1NF) (必须有主键,列不可分) 数据库表中的任何字段都是单一属性的,不可再分 create table aa(id int,NameAge varchar(100)) insert aa ...

  7. EFK教程(3) - ElasticSearch冷热数据分离

    基于ElasticSearch多实例架构,实现资源合理分配.冷热数据分离 作者:"发颠的小狼",欢迎转载与投稿 目录 ▪ 用途 ▪ 架构 ▪ 192.168.1.51 elasti ...

  8. code migrate

    1. 从Git上clone 仓库到本地. git clone --mirror http://gittest:gittest@192.168.1.x/x.git 2. push 到codecommit ...

  9. 从零开始在ubuntu上配置深度学习开发环境

    从零开始在ubuntu上配置深度学习开发环境 昨天一不小心把原来配置好的台式机的开发环境破坏了,调了半天没有调回来,索性就重装一次ubuntu系统.这篇文章主要记录一个简单的.‘傻瓜式’教程. 一.U ...

  10. <编译原理 - 函数绘图语言解释器(2)语法分析器 - python>

    <编译原理 - 函数绘图语言解释器(2)语法分析器 - python> 背景 编译原理上机实现一个对函数绘图语言的解释器 - 用除C外的不同种语言实现 设计思路: 设计函数绘图语言的文法, ...