题目:

给定一棵树, 带边权。

现在有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. vm虚拟机安装linux centos教程

    1 下载64btnhttp://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-1810.iso 2 vm注意选择cen ...

  2. Java基础知识之常量变量(一)

    1.什么是变量,什么是常量?java的基本数据类型是什么 变量: 会发生改变的数据,叫做变量,如自定义一个a,并且对a进行赋值操作为1,也可以让a等于2,此时a就是一个变量 常量: 不会发生改变的值, ...

  3. 对于 TCP 三次握手的理解

    假设名叫 A 和 B 的两个人要进行通信,那么他们两人之间,首先要确保通信顺畅. 而确保通信顺畅,就要从 3 个维度,确定 8 个能力 3 个维度分别是: 1.人知道(A 知道.B 知道) 2.人(A ...

  4. Redis实战--使用Jedis实现百万数据秒级插入

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 当我们 ...

  5. [干货]AspNetCore熟练应用CancellationToken,CTO会对你刮目相看

    背景 已经有很多文章记录了 web程序中采用异步编程的优势和.Net异步编程的用法, 异步编程虽然不能解决查询数据库的瓶颈, 但是利用线程切换,能最大限度的弹性利用工作线程, 提高了web服务的响应能 ...

  6. C语言|博客作业02

    这个作业属于哪个课程 C程序语言设计 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-1/homework/8654 我在这个课程的目标是 ...

  7. Redux中间件Redux-thunk的配置

    当做固定写法吧 截图里少一个括号,已代码为主 import {createStore,applyMiddleware,compose} from 'redux' import thunk from ' ...

  8. PL真有意思(六):子程序和控制抽象

    前言 在之前我们把抽象定义为一种过程,程序员可以通过它将一个名字与一段可能很复杂的程序片段关联起来.抽象最大的意义就在于,我们可以从功能和用途的角度来考虑它,而不是实现. 在大多数程序设计语言中,子程 ...

  9. yum运行报错:File "/usr/bin/yum", line 30 except KeyboardInterrupt, e: ^SyntaxError: invalid syntax

    这是由于Python升级导致 备份Python 历史版本 [root@sdw1 autoconf]# ls /usr/bin/python* [root@sdw1 autoconf]# mv /usr ...

  10. 设计模式之观察者模式--PHP

    列举一个场景:下班之后回家,打开家门,开始做饭,之后睡觉 以上场景如果按照传统的开始方式就是封装一个用户类,里面有回家方法,打开门方法,做饭方法,睡觉方法,之后在外面依次调用. 假设你代码开发完了,这 ...