【luogu P4114 Qtree1】 题解
题目链接:https://www.luogu.org/problemnew/show/P4114
1.把边权转化到点权:选取连接这条边的两个点中较深的一个。
2.查询点到点之间的边权时,要从seg[x]+1 到 seg[y],因为seg[x]其实连接的是上面一条边的边权。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define lson left, mid, rt<<1
#define rson mid + 1, right, rt<<1|1
using namespace std;
const ll maxn = 300000 + 10;
char opt[9];
ll n, m, root, res;
ll top[maxn], rev[maxn], seg[maxn], son[maxn];
ll fa[maxn], size[maxn], deep[maxn];
ll u[maxn], v[maxn], w[maxn];
ll tree[maxn<<2], lazy[maxn<<2], num, node[maxn];
struct edge{
ll next, from, to, len;
}e[maxn<<2];
ll head[maxn], cnt;
void add(ll u, ll v, ll w)
{
e[++cnt].from = u;
e[cnt].len = w;
e[cnt].next = head[u];
e[cnt].to = v;
head[u] = cnt;
}
//-----segment_tree-----
void PushUP(ll rt)
{
tree[rt] = max(tree[rt<<1], tree[rt<<1|1]);
}
void build(ll left, ll right, ll rt)
{
if(left == right)
{
tree[rt] = rev[left];
return;
}
ll mid = (left + right)>>1;
build(lson);
build(rson);
PushUP(rt);
}
void PushDOWN(ll rt)
{
lazy[rt<<1] = lazy[rt];
lazy[rt<<1|1] = lazy[rt];
tree[rt<<1] = lazy[rt];
tree[rt<<1|1] = lazy[rt];
lazy[rt] = 0;
}
void update(ll l, ll r, ll add, ll left, ll right, ll rt)
{
if(l <= left && r >= right)
{
tree[rt] = add;
lazy[rt] = add;
return;
}
ll mid = (left + right)>>1;
if(lazy[rt]) PushDOWN(rt);
if(l <= mid) update(l, r, add, lson);
if(r > mid) update(l, r, add, rson);
PushUP(rt);
}
ll query(ll l, ll r, ll left, ll right, ll rt)
{
ll res = -0x7fffffff;
if(l <= left && r >= right)
{
return tree[rt];
}
ll mid = (left + right)>>1;
if(lazy[rt]) PushDOWN(rt);
if(l <= mid) res = max(res, query(l, r, lson));
if(r > mid) res = max(res, query(l, r, rson));
return res;
}
//----------------------
void dfs1(ll u, ll f, ll d)
{
ll maxson = -1;
size[u] = 1;
deep[u] = d;
fa[u] = f;
for(ll i = head[u]; i != -1; i = e[i].next)
{
ll v = e[i].to;
if(f != v)
{
dfs1(v, u, d+1);
size[u] += size[v];
if(size[v] > maxson) son[u] = v, maxson = size[v];
}
}
}
void dfs2(ll u, ll t)
{
seg[u] = ++num;
rev[num] = node[u];
top[u] = t;
if(!son[u]) return;
dfs2(son[u], t);
for(ll i = head[u]; i != -1; i = e[i].next)
{
ll v = e[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v,v);
}
}
void updRange(ll x, ll y, ll k)
{
while(top[x] != top[y])
{
if(deep[top[x]] < deep[top[y]]) swap(x, y);
update(seg[top[x]], seg[x], k, 1, n, 1);
x = fa[top[x]];
}
if(deep[x] > deep[y]) swap(x, y);
update(seg[x], seg[y], k, 1, n, 1);
}
ll qRange(ll x, ll y)
{
ll ans = 0;
while(top[x] != top[y])
{
if(deep[top[x]] < deep[top[y]]) swap(x, y);
res = 0;
res = query(seg[top[x]], seg[x], 1, n, 1);
ans = max(res, ans);
x = fa[top[x]];
}
if(deep[x] > deep[y]) swap(x, y);
res = 0;
res = query(seg[x]+1, seg[y], 1, n, 1);
ans = max(res, ans);
return ans;
}
int main()
{
memset(head, -1, sizeof(head));
scanf("%lld",&n);
root = 1;
for(ll i = 1; i < n; i++)
{
scanf("%lld%lld%lld",&u[i],&v[i],&w[i]);
add(u[i],v[i],w[i]); add(v[i],u[i],w[i]);
}
dfs1(root, 0, 1);
//for(int i = 1; i <= n; i++) cout<<deep[i]<<" ";
for(ll i = 1; i < n; i++)
{
if(deep[u[i]] < deep[v[i]]) node[v[i]] = w[i];
else node[u[i]] = w[i];
}
//for(int i = 1; i <= n; i++) cout<<node[i]<<" ";
dfs2(root, root);
build(1, n, 1);
while(cin>>opt && opt[0] != 'D')
{
ll x, y, z;
if(opt[0] == 'C')
{
scanf("%lld%lld",&x,&y);
if(deep[u[x]] > deep[v[x]]) updRange(u[x], u[x], y);
else updRange(v[x], v[x], y);
}
else
{
scanf("%lld%lld",&x,&y);
if(x == y)
{
printf("0\n");
continue;
}
printf("%lld\n",qRange(x,y));
}
}
}
【luogu P4114 Qtree1】 题解的更多相关文章
- 洛谷 P4114 Qtree1 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 说明 思路 Change Query AC代码 总结 题面 题目链接 P4114 Qt ...
- 洛谷 - P4114 - Qtree1 - 重链剖分
https://www.luogu.org/problem/P4114 维护边权的话,用深度大的点表示这条边(可以遍历一边边询问两端深度,这样不需要修改dfs1,也可以在dfs1的时候向下走的同时把边 ...
- 【luogu P3946 ことりのおやつ】 题解
题目链接:https://www.luogu.org/problemnew/show/P3946 交好几遍是因为虽然能过一直有提醒..强迫症qwq #include <bits/stdc++.h ...
- 洛谷P4114 Qtree1
题目描述 给定一棵\(n\)个节点的树,有两个操作: \(CHANGE\) \(i\) \(t_i\) 把第\(i\)条边的边权变成\(t_i\) \(QUERY\) \(a\) \(b\) 输出从\ ...
- Luogu P2210 Haywire 题解
其实这题吧...有一种玄学解法 这题的要求的就是一个最小化的顺序 那么,我们就不进想到了一种显然的写法 就是random_shuffle 什么?这不是乱搞的非正解吗 然而,正如一句话说的好 一个算法, ...
- [Luogu P4178]Tree 题解(点分治+平衡树)
题目大意 给定一棵树,边带权,问有多少点对满足二者间距离$\leq K$,$n \leq 40000$. 题解 点分治专题首杀!$Jackpot!$ (本来看着题意比较简单想捡个软柿子捏,结果手断了… ...
- [火星补锅] 水题大战Vol.2 T1 && luogu P1904 天际线 题解 (线段树)
前言: 当时考场上并没有想出来...后来也是看了题解才明白 解析: 大家(除了我)都知道,奇点和偶点会成对出现,而出现的前提就是建筑的高度突然发生变化.(这个性质挺重要的,我之前没看出来) 所以就可以 ...
- Luogu P2158 仪仗队 题解报告
题目传送门 [题目大意] 给定一个n×n的点方阵,求站在左下角的点能看到的点数 注意同一条直线上只能看到一个点 [思路分析] 因为是一个方阵,所以可以对称地算,那么对于半个方阵,这里假设是左上的半个方 ...
- P4114 Qtree1
思路 树剖一发,注意对LCA的处理 代码 #include <cstdio> #include <algorithm> #include <cstring> usi ...
随机推荐
- Bootstrap 斜体、文本对齐、缩略图、地址、列表等
目录1.标题2.页面主体3.强调 a.小号文本 b.着重 c.斜体 d.对齐class e.强调class4.缩略语5.地址6.列表 a.无序列表 b.有序列 ...
- CSS布局——左定宽度右自适应宽度并且等高布局
方法一: 别的不多说,直接上代码,或者参考在线DEMO,下面所有的DEMO都有HTML和CSS代码,感兴趣的同学自己慢慢看吧. HTML Markup <div id="contain ...
- js 中移动元素的方法
2017-12-13 19:59:24 <!DOCTYPE html> <html lang="en"> <head> <meta cha ...
- 《Python编程从入门到实践》_第三章_列表简介
什么是列表呢? 官方说明就是由一些列按特点顺序排列的元素组成.其实可以看出很多个字符串的有序组合吧,里面的内容可以随时的删除,增加,修改. 下面这个就是一个列表,python打印列表的时候会将中括号和 ...
- 使用mini-define实现前端代码的模块化管理
这篇文章主要介绍了使用mini-define实现前端代码的模块化管理,十分不错的一篇文章,这里推荐给有需要的小伙伴. mini-define 依据require实现的简易的前端模块化框架.如果你不想花 ...
- 文档碎片DocumentFragment
文档碎片是什么? 参考标准的描述,DocumentFragment是一个轻量级的文档对象,能够提取部分文档的树或创建一个新的文档片段,换句话说有文档缓存的作用. createDocumentFragm ...
- 4、Angular2 pipe
1. stateless pipe 2.stateful pipe
- 人民币金额大小写Js转换
/** * 数字转中文 * @param dValue * @returns */ function chineseNumber(dValue) { var maxDec = 2; // 验证输入金额 ...
- SpringSecurity 3.2入门(2)环境搭建
由于目前Spring官方只提供Meven的下载方式,为了能以最快的速度入门使用框架,这里提供百度网盘下载链接. 注:本入门教程默认已经配置成功SpringMVC框架. 1.web.xml配置 < ...
- 认识Spring AOP
Spring AOP AOP是Aspect/'æspekt/ Oriented/ɔːrɪentɪd/ Programming的缩写,意为:面向切面编程. 是什么 通过预编译方式和运行期动态代理实现程序 ...