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. 主攻互动娱乐和视频自媒体,新浪SHOW是不是桩好生意?

        对互联网互动服务平台而言,近期几年会是空前重要的发展阶段,首先,互联网行业的持续发展.网民数量的持续激增必定带动网络互动朝更普及的方向迈进.其市场规模也必定会呈极数增长.其次,互动娱乐.视频自 ...

  2. 通过反射 往泛型Integer的集合里添加String 类型的数据 Day25

    package com.sxt.method1; import java.lang.reflect.Method; /* * 需求:通过反射 往泛型Integer的集合里添加String 类型的数据 ...

  3. TIJ——Chapter Three:Operators

    Operators 本章节比较简单,所以简单的做一些笔记: 几个要点: 1.When the compiler sees a String followed by a "+" fo ...

  4. SharpDX初学者教程第5部分:着色三角形

    原文 http://www.johanfalk.eu/blog/sharpdx-beginners-tutorial-part-5-coloring-the-triangle 在第4部分中,我们创建了 ...

  5. iOS编译错误#ld: warning: ignoring file# 之 Undefined symbols for architecture x86_64 - ld: symbol(s) not found for architecture x86_64

    ld: warning: ignoring file xxxPath/libbaidumapapi.a, missing required architecture x86_64 in file xx ...

  6. Python深入:修改Python搜索路径

    当Python执行import语句时,它会在一些路径中搜索Python模块和扩展模块.可以通过sys.path查看这些路径,比如: >>> import sys >>&g ...

  7. HZOJ 走格子

    作者的正解: 对于100%的数据:行动可以分为两种: 1. 步行,花费一个单位的时间移动到4联通的相邻格子中去. 2. 使用传送门,指定一个方向的墙的前面的一个格子,步行至最近的一个墙的面前,使用传送 ...

  8. Android的headerView和emptyView共存问题

    今天做项目的时候,准备优化下ListView相关的东西,于是乎,需要做一个当列表无数据时,空的提醒页面.这个自然想到的是ListView的setEmptyView()方法,于是顺手就写了,可是,当我为 ...

  9. 2012.2.1datagridview用法小结

    dgv1.RowHeadersVisible = false; //最左侧栏消失 dgv1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode. ...

  10. 利用 jquery 获取某个元素下的所有图片并改变其属性

    HTML代码 <div id="mochu"> <p>内容....<./p> <p><img src="xxxx.p ...