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 树链剖分 边权的更多相关文章

  1. POJ3237 Tree 树链剖分 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...

  2. POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12247   Accepted: 3151 Descriptio ...

  3. 计蒜客 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 ...

  4. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...

  5. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

  6. POJ2763 Housewife Wind 树链剖分 边权

    POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...

  7. HDU3669 Aragorn's Story 树链剖分 点权

    HDU3669 Aragorn's Story 树链剖分 点权 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: n个点的,m条边,每个点都 ...

  8. poj3237树链剖分边权+区间取负

    树链剖分+线段树lazy-tag在树链上操作时千万不要写错.. /* 树链剖分+线段树区间变负 */ #include<iostream> #include<cstring> ...

  9. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

随机推荐

  1. Chrome的使用技巧总结

    设置一>” 首先设置打开特定的网页 设置--> “下载位置” (Ctrl+H),快速查找自己浏览器访问网页的历史记录 (Ctrl+D),将目前认为比较好的网页保存. ctrl+t  新建标 ...

  2. Nuxt.js打造旅游网站第2篇_首页开发

    页面效果: 1.初始化默认布局 nuxtjs提供了一个公共布局组件layouts/default.vue,该布局组件默认作用于所有页面,所以我们可以在这里加上一些公共样式,在下一小结中还会导入公共组件 ...

  3. PostgreSQL重新读取pg_hba.conf文件

    PostgreSQL  配置文件之pg_hba.conf 该文件用于控制访问安全性,管理客户端对于PostgreSQL服务器的访问权限,内容包括:允许哪些用户连接到哪个数据库,允许哪些IP或者哪个网段 ...

  4. jsp中几注释的区别

    1).JSP页面中的HTML注释 SP页面中的HTML注释使用“<!—”和“-->”创建,它的具体形式如下所示: <!-- 注释内容 --> 当它出现在JSP页面时,微蘑菇将不 ...

  5. Javascript用正则表达式replace替换父串中所有符合条件的子串

    这样用,只会替换匹配到的第一个子串 str = 'I hava a pen ,I hava an apple,apple pen, pen apple' str = str.replace('appl ...

  6. Linux服务部署:nginx服务 nfs服务

    nginx服务 源码安装: yum install gcc-* glibc-* openssl openssl-devel pcre pcre-devel zlib zlib-devel -ylsta ...

  7. 详解Python中内置的NotImplemented类型的用法

    它是什么? ? 1 2 >>> type(NotImplemented) <type 'NotImplementedType'> NotImplemented 是Pyth ...

  8. Oracle包utl_inaddr

    作用:用于取得局域网或Internet环境中的主机名和IP地址. 1.utl_inaddr.get_host_address 环境中IP地址 如果查询失败,则提示系统错误 查询www.qq.com的I ...

  9. PHP 7.0新增特性详解

    https://www.cnblogs.com/riverdubu/archive/2017/03/22/6434705.html 开始介绍PHP7.0新特性,具体的可以参照官网的介绍,我来挑一些给大 ...

  10. 【BestCoder Round #93 1004】MG loves set

    [题目链接]:http://acm.hdu.edu.cn/showproblem.php?pid=6022 [题意] 让你求一个集合的子集数目; 这个子集有要求; 即: 它所有元素的平方的和小于它所有 ...