POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权
传送门:http://poj.org/problem?id=3237
题意:
n个点的,n-1条边
修改单边边权
将a->b的边权取反
查询a->b边权最大值
题解:
修改边权就查询点的深度大的点,用大的点去存这条边的边权,其余的就和点权的是一样的了
取反操作用线段树维护,区间最大值取反就是区间最小值,区间最小值取反就是区间最大值
所以维护两颗线段树即可,lazy标记表示覆盖单边的边权
代码:
#include <set>
#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 1e5 + 5;
const int INF = 0x3f3f3f3f;
struct EDGE {
int v, nxt, w;
} edge[maxn << 1];
int head[maxn], tot;
void add_edge(int u, int v, int w) {
edge[tot].v = v;
edge[tot].w = w;
edge[tot].nxt = head[u];
head[u] = tot++;
}
int sz[maxn], dep[maxn], son[maxn], id[maxn], Rank[maxn], cnt, fa[maxn], top[maxn];
int d[maxn];
void dfs1(int u, int f, int cnt) {
fa[u] = f;
dep[u] = cnt;
sz[u] = 1;
son[u] = 0;
int tmp = 0;
for(int i = head[u]; i != -1; i = edge[i].nxt) {
int v = edge[i].v;
if(v != f) {
dfs1(v, u, cnt + 1);
if(tmp < sz[v]) {
son[u] = v;
tmp = sz[v];
}
sz[u] += sz[v];
}
}
}
void dfs2(int u, int tp) {
top[u] = tp;
id[u] = ++cnt;
Rank[cnt] = u;
if(son[u]) dfs2(son[u], tp);
for(int i = head[u]; i != -1; i = edge[i].nxt) {
int v = edge[i].v;
if(v == fa[u]) continue;
if(v == son[u]) {
d[id[v]] = edge[i].w;
continue;
}
dfs2(v, v);
d[id[v]] = edge[i].w;
}
}
void prebuild() {
dfs1(1, 0, 0);
dfs2(1, 1);
}
int Max[maxn << 2];
int Min[maxn << 2];
// int sum[maxn<<2];
int lazy[maxn];
void push_up(int rt) {
Max[rt] = max(Max[ls], Max[rs]);
Min[rt] = min(Min[ls], Min[rs]);
}
void build(int l, int r, int rt) {
lazy[rt] = 1;
if(l == r) {
Max[rt] = Min[rt] = d[l];
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
push_up(rt);
}
void push_down(int rt) {
if(lazy[rt] == -1) {
lazy[ls] = -lazy[ls];
lazy[rs] = -lazy[rs];
lazy[rt] = 1;
swap(Max[ls], Min[ls]);
Max[ls] *= -1;
Min[ls] *= -1;
swap(Max[rs], Min[rs]);
Max[rs] *= -1;
Min[rs] *= -1;
}
}
void update_pos(int pos, int val, int l, int r, int rt) {
if(l == r) {
lazy[rt] = 1;
Max[rt] = Min[rt] = val;
return;
}
push_down(rt);
int mid = (l + r) >> 1;
if(pos <= mid) update_pos(pos, val, lson);
else update_pos(pos, val, rson);
push_up(rt);
}
void update(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
lazy[rt] = -lazy[rt];
swap(Max[rt], Min[rt]);
Max[rt] *= -1;
Min[rt] *= -1;
return;
}
push_down(rt);
int mid = (l + r) >> 1;
if(L <= mid) update(L, R, lson);
if(R > mid) update(L, R, rson);
push_up(rt);
}
int query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
return Max[rt];
}
push_down(rt);
int mid = (l + r) >> 1;
int ans = -INF;
if(L <= mid) ans = max(ans, query(L, R, lson));
if(R > mid) ans = max(ans, query(L, R, rson));
return ans;
}
void change(int u, int v) {
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) {
swap(u, v);
}
update(id[top[u]], id[u], 1, cnt, 1);
u = fa[top[u]];
}
if(u != v) {
if(dep[u] > dep[v]) swap(u, v);
update(id[son[u]], id[v], 1, cnt, 1);
}
}
void Query(int u, int v) {
int ans = -INF;
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) {
swap(u, v);
}
ans = max(ans, query(id[top[u]], id[u], 1, cnt, 1));
u = fa[top[u]];
}
if(u != v) {
if(dep[u] > dep[v]) swap(u, v);
ans = max(ans, query(id[son[u]], id[v], 1, cnt, 1));
}
printf("%d\n", ans);
}
int u[maxn], v[maxn], c[maxn];
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int n, T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
memset(head, -1, sizeof(head));
tot = cnt = 0;
for(int i = 1; i < n; i++) {
scanf("%d%d%d", &u[i], &v[i], &c[i]); //要用数组保存
add_edge(u[i], v[i], c[i]);
add_edge(v[i], u[i], c[i]);
}
prebuild();
build(1, cnt, 1);
char op[20];
int a, b;
while(1) {
scanf("%s", op);
if(op[0] == 'D') break;
scanf("%d%d", &a, &b);
if(op[0] == 'C') {
int tmp = dep[u[a]] > dep[v[a]] ? u[a] : v[a]; //找出深度大的那个点
update_pos(id[tmp], b, 1, cnt, 1); //更新进入深度大的点那条边
} else if(op[0] == 'N') change(a, b);
else if(op[0] == 'Q') Query(a, b);
}
}
return 0;
}
POJ3237 Tree 树链剖分 边权的更多相关文章
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 12247 Accepted: 3151 Descriptio ...
- 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)
Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- POJ2763 Housewife Wind 树链剖分 边权
POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...
- HDU3669 Aragorn's Story 树链剖分 点权
HDU3669 Aragorn's Story 树链剖分 点权 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: n个点的,m条边,每个点都 ...
- poj3237树链剖分边权+区间取负
树链剖分+线段树lazy-tag在树链上操作时千万不要写错.. /* 树链剖分+线段树区间变负 */ #include<iostream> #include<cstring> ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
随机推荐
- bzoj1191 超级英雄
Description 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的多少获得不同数目的奖品或奖金.主持人问题准备了若干道题目,只有当选手正确回 ...
- 【JZOJ4890】【NOIP2016提高A组集训第14场11.12】随机游走
题目描述 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己 ...
- rm: cannot remove `libtoolT’: No such file or directory
安装源码包第一步./configure检测是否可编译时,检测出问题rm: cannot remove `libtoolT’: No such file or directory 解决方案:将confi ...
- GDB调试命令手册
使用GDB 启动 $ gdb program # program是你的可执行文件,一般在当前目录 $ gdb program core # gdb同时调试运行程序和cor ...
- MaxCompute 图计算用户手册(下)
示例程序 强连通分量 在有向图中,如果从任意一个顶点出发,都能通过图中的边到达图中的每一个顶点,则称之为强连通图.一张有向图的顶点数极大的强连通子图称为强连通分量.此算法示例基于 parallel C ...
- 【Linux】 经典Linux系统工程师面试题(转载)
1.如何将本地80端口的请求转发到8080端口,当前主机IP为192.168.16.1,其中本地网卡eth0: 答: # iptables -t nat -A PREROUTING -d 192.16 ...
- 【转载】Ubuntu终端常用的快捷键
Ubuntu中的许多操作在终端(Terminal)中十分的快捷,记住一些快捷键的操作更得心应手.在Ubuntu中打开终端的快捷键是Ctrl+Alt+T.其他的一些常用的快捷键如下: 快捷键 功能 Ta ...
- hdu 3652 【数位dp】
hdu 3652 题意:求1到n中包含'13'('13'不一定连续)且能被13整除的数的个数. 这是我第一道比较了能看懂的数位dp.定义状态dp[pos][res][sta]表示处理到第pos位,模的 ...
- KiCad EDA 5.1.2 使用圆形板框时出现无法走线的问题
KiCad EDA 5.1.2 使用圆形板框时出现无法走线的问题 看到官方已经修复,等着官方发布新的版本 5.1.3. Steps to reproduce: 1) create new board. ...
- 创建ROS 工作空间时出现:程序“catkin_init_workspace”尚未安装,程序“catkin_make”尚未安装。
问题:创建ROS 工作空间时出现:程序“catkin_init_workspace”尚未安装,程序“catkin_make”尚未安装. 解决方法: source /opt/ros/kinetic/se ...