Luogu P1505.[国家集训队]旅游
题解
真真正正是个码农题,不过很套路,熟练就打得很快,不过要用点维护边的信息在 \(\text{LCA}\) 出要注意,不能处理此点的信息
\(Code\)
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N = 2e5 + 5;
int n, m, h[N];
struct edge{int to, nxt, w, id;}e[N << 1];
inline void add(int u, int v, int w, int id)
{
static int tot = 0;
e[++tot] = edge{v, h[u], w, id}, h[u] = tot;
}
int top[N], fa[N], dfn[N], dep[N], siz[N], son[N], ver[N], edg[N];
void dfs1(int x)
{
siz[x] = 1;
for(register int i = h[x]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == fa[x]) continue;
edg[v] = e[i].w, ver[e[i].id] = v, fa[v] = x, dep[v] = dep[x] + 1, dfs1(v), siz[x] += siz[v];
if (siz[v] > siz[son[x]]) son[x] = v;
}
}
void dfs2(int x)
{
static int dfc = 0;
dfn[x] = ++dfc;
if (son[x]) top[son[x]] = top[x], dfs2(son[x]);
for(register int i = h[x]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == fa[x] || v == son[x]) continue;
top[v] = v, dfs2(v);
}
}
struct Tree{
#define ls (p << 1)
#define rs (ls | 1)
const int INF = 0x3f3f3f3f;
int sum[N << 2], mn[N << 2], mx[N << 2], tag[N << 2];
inline Tree(){memset(mn, 0x3f3f3f3f, sizeof mn), memset(mx, -0x3f3f3f3f, sizeof mx);}
void change(int p){sum[p] *= -1, mx[p] *= -1, mn[p] *= -1, swap(mx[p], mn[p]), tag[p] ^= 1;}
void pushup(int p){sum[p] = sum[ls] + sum[rs], mn[p] = min(mn[ls], mn[rs]), mx[p] = max(mx[ls], mx[rs]);}
void pushdown(int p)
{
if (!tag[p]) return;
change(ls), change(rs), tag[p] ^= 1;
}
void update_node(int p, int l, int r, int x, int v)
{
if (l == r)
{
sum[p] = mn[p] = mx[p] = v;
if (l == 1) mn[p] = INF, mx[p] = -INF;
return;
}
pushdown(p);
int mid = (l + r) >> 1;
if (x <= mid) update_node(ls, l, mid, x, v);
else update_node(rs, mid + 1, r, x, v);
pushup(p);
}
void update_rev(int p, int l, int r, int x, int y)
{
if (x <= l && r <= y) return void(change(p));
pushdown(p);
int mid = (l + r) >> 1;
if (x <= mid) update_rev(ls, l, mid, x, y);
if (y > mid) update_rev(rs, mid + 1, r, x, y);
pushup(p);
}
inline void tree_rev(int x, int y)
{
int fx = top[x], fy = top[y];
while (fx ^ fy)
{
if (dep[fx] > dep[fy]) update_rev(1, 1, n, dfn[fx], dfn[x]), x = fa[fx], fx = top[x];
else update_rev(1, 1, n, dfn[fy], dfn[y]), y = fa[fy], fy = top[y];
}
if (dep[x] > dep[y]) swap(x, y);
if (x == y) return;
update_rev(1, 1, n, dfn[x] + 1, dfn[y]);
}
int query_sum(int p, int l, int r, int x, int y)
{
if (x <= l && r <= y) return sum[p];
pushdown(p);
int mid = (l + r) >> 1, ret = 0;
if (x <= mid) ret += query_sum(ls, l, mid, x, y);
if (y > mid) ret += query_sum(rs, mid + 1, r, x, y);
return ret;
}
inline int tree_sum(int x, int y)
{
int fx = top[x], fy = top[y], ret = 0;
while (fx ^ fy)
{
if (dep[fx] > dep[fy]) ret += query_sum(1, 1, n, dfn[fx], dfn[x]), x = fa[fx], fx = top[x];
else ret += query_sum(1, 1, n, dfn[fy], dfn[y]), y = fa[fy], fy = top[y];
}
if (dep[x] > dep[y]) swap(x, y);
if (x == y) return ret;
return ret + query_sum(1, 1, n, dfn[x] + 1, dfn[y]);
}
int query_max(int p, int l, int r, int x, int y)
{
if (x <= l && r <= y) return mx[p];
pushdown(p);
int mid = (l + r) >> 1, ret = -INF;
if (x <= mid) ret = max(ret, query_max(ls, l, mid, x, y));
if (y > mid) ret = max(ret, query_max(rs, mid + 1, r, x, y));
return ret;
}
inline int tree_max(int x, int y)
{
int fx = top[x], fy = top[y], ret = -INF;
while (fx ^ fy)
{
if (dep[fx] > dep[fy]) ret = max(ret, query_max(1, 1, n, dfn[fx], dfn[x])), x = fa[fx], fx = top[x];
else ret = max(ret, query_max(1, 1, n, dfn[fy], dfn[y])), y = fa[fy], fy = top[y];
}
if (dep[x] > dep[y]) swap(x, y);
if (x == y) return ret;
return max(ret, query_max(1, 1, n, dfn[x] + 1, dfn[y]));
}
int query_min(int p, int l, int r, int x, int y)
{
if (x <= l && r <= y) return mn[p];
pushdown(p);
int mid = (l + r) >> 1, ret = INF;
if (x <= mid) ret = min(ret, query_min(ls, l, mid, x, y));
if (y > mid) ret = min(ret, query_min(rs, mid + 1, r, x, y));
return ret;
}
inline int tree_min(int x, int y)
{
int fx = top[x], fy = top[y], ret = INF;
while (fx ^ fy)
{
if (dep[fx] > dep[fy]) ret = min(ret, query_min(1, 1, n, dfn[fx], dfn[x])), x = fa[fx], fx = top[x];
else ret = min(ret, query_min(1, 1, n, dfn[fy], dfn[y])), y = fa[fy], fy = top[y];
}
if (dep[x] > dep[y]) swap(x, y);
if (x == y) return ret;
return min(ret, query_min(1, 1, n, dfn[x] + 1, dfn[y]));
}
}seg;
int main()
{
scanf("%d", &n);
for(register int i = 1, u, v, w; i < n; i++)
scanf("%d%d%d", &u, &v, &w), ++u, ++v, add(u, v, w, i), add(v, u, w, i);
dfs1(1), top[1] = 1, dfs2(1);
for(register int i = 1; i <= n; i++) seg.update_node(1, 1, n, dfn[i], edg[i]);
scanf("%d", &m);
char op[5];
for(int u, v; m; --m)
{
scanf("%s%d%d", op, &u, &v), ++u, ++v;
if (op[0] == 'C') seg.update_node(1, 1, n, dfn[ver[u - 1]], v - 1);
else if (op[0] == 'N') seg.tree_rev(u, v);
else if (op[0] == 'S') printf("%d\n", seg.tree_sum(u, v));
else if (op[1] == 'A') printf("%d\n", seg.tree_max(u, v));
else printf("%d\n", seg.tree_min(u, v));
}
}
Luogu P1505.[国家集训队]旅游的更多相关文章
- LUOGU P1505 [国家集训队]旅游 (树链剖分+线段树)
传送门 解题思路 快被调死的码农题,,,其实就是一个边权下放到点权的线段树+树剖. #include<iostream> #include<cstdio> #include&l ...
- 洛谷 P1505 [国家集训队]旅游 解题报告
P1505 [国家集训队]旅游 题目描述 \(\tt{Ray}\) 乐忠于旅游,这次他来到了\(T\)城.\(T\)城是一个水上城市,一共有 \(N\) 个景点,有些景点之间会用一座桥连接.为了方便游 ...
- 洛谷 P1505 [国家集训队]旅游 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 AC代码 总结 题面 题目链接 P1505 [国家集训队]旅游 题目描述 Ray 乐 ...
- 2018.06.29 洛谷P1505 [国家集训队]旅游(树链剖分)
旅游 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有 ...
- P1505 [国家集训队]旅游
\(\color{#0066ff}{题 目 描 述}\) Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了 ...
- 洛谷P1505 [国家集训队]旅游
题目描述 \(Ray\) 乐忠于旅游,这次他来到了\(T\) 城.\(T\) 城是一个水上城市,一共有 \(N\) 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,\(T ...
- P1505 [国家集训队]旅游[树剖]
题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路 ...
- 洛谷P1505 [国家集训队]旅游(树剖+线段树)
传送门 这该死的码农题…… 把每一条边变为它连接的两个点中深度较浅的那一个,然后就是一堆单点修改/路径查询,不讲了 这里就讲一下怎么搞路径取反,只要打一个标记就好了,然后把区间和取反,最大最小值交换然 ...
- [洛谷]P1505 [国家集训队]旅游
题目链接: 传送门 题目分析: 树剖板,支持单点修改,区间取反,区间求最大值/最小值/和 区间取反取两次等于没取,维护一个\(rev\ tag\),每次打标记用\(xor\)打,记录是否需要翻转,\( ...
- luoguP1505 [国家集训队]旅游(真的毒瘤)
luogu P1505 [国家集训队]旅游 题目 #include<iostream> #include<cstdio> #include<cstdlib> #in ...
随机推荐
- go slice不同初始化方式性能&数组比较
go语言开发中,slice是我们常用的数据类型之一,也是因为它的灵活性,自己也很少使用数组,当然我也知道它的一些特性,不过没有真实的去验证它,因为大多数使用场景没必要对code太过苛刻,但是如果封装作 ...
- 1.1 大数据简介-hadoop-最全最完整的保姆级的java大数据学习资料
目录 1 hadoop-最全最完整的保姆级的java大数据学习资料 1.1 大数据简介 1.1.1 大数据的定义 1.1.2 大数据的特点 1.1.3 大数据的应用场景 1.1.4 大数据的发展趋势及 ...
- 推荐8个提高工作效率的IntelliJ插件
前言 欢迎关注微信公众号「JAVA旭阳」交流和学习 IntelliJ目前已经成为市面上最受欢迎的Java开发工具,这得益于里面非常丰富的插件机制.本文我将分享在日常开发中我经常使用的5个插件,它们可以 ...
- [whk] 解三元一次方程
注:本篇运用大量 Katex ,如果炸了可能是运存不够也可能还要加载一会,重进几次即可.(都2202了,居然还存在我这种会炸公式的笔记本) 前言 写这篇随笔的由来是今天学习了: 不共线三点确定二次函数 ...
- 论文解读(CAN)《Contrastive Adaptation Network for Unsupervised Domain Adaptation》
论文信息 论文标题:Contrastive Adaptation Network for Unsupervised Domain Adaptation论文作者:Guoliang Kang, Lu Ji ...
- [sklearn] 决策树、随机森林、隐马尔可夫模型
决策树 决策树(Decision Tree)是一种用于处理分类和回归问题的无监督学习算法.如下图所示为某女青年在某相亲网站的相亲决策图.这幅图描述的都是一个非常典型的决策树模型. 通过对其相亲决策的分 ...
- Google分布式文件系统GFS论文学习
GFS作为最著名的分布式文件系统,首先具备了大规模.可扩展.适配大文件.自动运维等高级特性.虽然是比较早期的分布式文件系统,但是它里面的设计思想还是值得现代分布式系统设计参考的,并且还有很多后期著名的 ...
- python网络爬虫数据解析之正则
本节内容,讲解爬取网络图片,利用正则匹配图片地址 请求网页之后,响应部分内容如下图: 1 时间:2023/1/7 10:42 2 功能描述 3 1.进行指定标签的定位 4 2.标签或者标签对应的属性中 ...
- CLISP学习(二)
它是一门函数式语言,你要用函数的思维来思考. 只不过与数学的表达不同的是,数学里的函数是在括号外 f(x) ,而lisp是在括号内,以列表的形式(f x), cos(x) --> (cos x ...
- day03-Spring管理Bean-IOC-01
Spring管理Bean-IOC 1.Spring配置/管理bean介绍 Bean管理包括两方面: 创建bean对象 给bean注入属性 Bean的配置方式: 基于xml文件配置方式 基于注解配置方式 ...