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. 2019-9-2-win10-uwp-随着数字变化颜色控件

    title author date CreateTime categories win10 uwp 随着数字变化颜色控件 lindexi 2019-09-02 12:57:38 +0800 2018- ...

  2. Gym - 101617D_Jumping Haybales(BFS)

    Sample Input 4 2 .### #... .#.. #.#. 3 1 .#. .#. .#. Sample Output 4 -1 题意:给一个n*n的图,每次最多能跳k个格子,只能向南( ...

  3. Resharper 如何把类里的类移动到其他文件

    有时候,看到一个类里有很多类,需要把他移动其他文件 假如有一个类 class A { class B { } } 如何把 B 移动文件 B里? 一般使用 快捷键是 Resharper 的快捷键,如果不 ...

  4. mongodb Helper

    /// <summary> /// mongoDBHelper访问助手 /// </summary> public class mongoDBHelper { /// < ...

  5. oracle 优化GROUP BY

    提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多. 低效: SELECT JOB , AVG(SAL) FROM ...

  6. ∆ (triangle)

    2.1 题目描述 给定一个无自环重边的无向图,求这个图的三元环1的个数以及补图2的三元环个数. 2.2 输入格式 第一行 2 个数 n, m ,分别表示图的点数.边数. 接下来 m 行,每行两个数 u ...

  7. phpStudy本地环境测试,打开网页很慢的解决办法!

    很多人应该都遇到了在使用phpStudy本地环境测试软件时候打开很慢的问题,甚至动辄达到了1000ms以上,开篇直接给出解决办法: 下面给大家介绍phpstudy访问速度慢的解决办法. 1.修改mys ...

  8. springmvc 多文件/文件夹上传 下载

    注入依赖 <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding&g ...

  9. UA判断打开页面的环境,然后在callBack写相应环境下的回调函数

    这是js代码 /* * 2016.11.10 * SunJingxin * V 1.0.0 * */ (function(){ /* * 使用方法: * 一.引入ua.js * 二.直接调用 Mobi ...

  10. [转载] linux find 命令

    转载自 http://www.jb51.net/os/RedHat/1307.html Linux下find命令在目录结构中搜索文件,并执行指定的操作. Linux下find命令提供了相当多的查找条件 ...