POJ3237-Tree (树链剖分,线段树区间更新+点更新+区间查询)
两个更新操作,一个将第i条路径权值改为w,一个是将a-b之间所有路径权值取反。
一个查询操作,求a-b之间路径中权值最大的边。
很容易想到维护一个最大最小值,取反就是把最大最小取反交换一下。
开始遇到一个问题就是我把根节点赋值0,上一道题求和没问题,但是这道题会出问题,于是线段树建树的时候从2开始建的,第一次尝试这么写,不过也没什么问题。
wa了一天。。。。
一开始的错是pushdown的时候没有把子节点的fg更新,于是我改了fg[lson]=fg[rson]=1。。。。。。。。
就这样。。。。我对着这份代码看了几个小时。。。。。找数据。。。后来自己写了发对拍。。。。
后来终于忍不了了。。。。找了别人的代码。。。。
哦,应该是fg[lson] ^= 1; fg[rson] ^= 1;
我果然不会线段树。。。。。
mdzz
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;
const int N = ; //
struct Edge {
int to, next, cost, id;
} edge[N*];
int head[N], cntE;
void addedge(int u, int v, int w, int id) {
edge[cntE].to = v; edge[cntE].next = head[u]; edge[cntE].cost = w; edge[cntE].id = id; head[u] = cntE++;
edge[cntE].to = u; edge[cntE].next = head[v]; edge[cntE].cost = w; edge[cntE].id = id; head[v] = cntE++;
}
//
int dep[N], sz[N], fa[N], son[N], son_cost[N];
int road[N];
void dfs1(int u, int par, int d) {
dep[u] = d; sz[u] = ; fa[u] = par;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (v != par) {
road[edge[i].id] = v;
dfs1(v, u, d+);
sz[u] += sz[v];
if (son[u] == - || sz[v] > sz[son[u]]) {
son[u] = v;
son_cost[u] = edge[i].cost;
}
}
}
}
int top[N], dfn[N], rk[N], idx;
int a[N];
void dfs2(int u, int rt, int cost) {
top[u] = rt; dfn[u] = ++idx; a[idx] = cost;
if (son[u] == -) return;
dfs2(son[u], rt, son_cost[u]);
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (v != fa[u] && v != son[u]) dfs2(v, v, edge[i].cost);
}
} //
int mx[N<<], fg[N<<], mi[N<<];
#define lson o<<1
#define rson o<<1|1 void pushdown(int o) {
if (fg[o]) {
fg[lson] ^= ;
fg[rson] ^= ;
int tmp = mx[lson];
mx[lson] = -mi[lson];
mi[lson] = -tmp;
tmp = mx[rson];
mx[rson] = -mi[rson];
mi[rson] = -tmp;
fg[o] = ;
}
} void pushup(int o) {
mx[o] = max(mx[lson], mx[rson]);
mi[o] = min(mi[lson], mi[rson]);
} void build(int o, int l, int r) {
fg[o] = ;
if (l == r) {
mx[o] = a[l];
mi[o] = a[l];
} else {
int mid = (l+r) >> ;
build(lson, l, mid);
build(rson, mid+, r);
pushup(o);
}
} void CHANGE(int o, int l, int r, int v, int w) {
if (l == r) {
mi[o] = mx[o] = w;
} else {
pushdown(o);
int mid = (l + r) >> ;
if (mid >= v) CHANGE(lson, l, mid, v, w);
else CHANGE(rson, mid+, r, v, w);
pushup(o);
}
} void nega(int o, int l, int r, int L, int R) {
if (l >= L && r <= R) {
fg[o] ^= ;
int tmp = mx[o];
mx[o] = -mi[o];
mi[o] = -tmp;
return;
}
pushdown(o);
int mid = (l+r) >> ;
if (mid >= L) nega(lson, l, mid, L, R);
if (mid < R) nega(rson, mid+, r, L, R);
pushup(o);
} void NEGATE(int x, int y, int n) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
nega(, , n, dfn[top[x]], dfn[x]);
x = fa[top[x]];
}
if (x == y) return ;
if (dep[x] > dep[y]) swap(x, y);
nega(, , n, dfn[son[x]], dfn[y]);
} int query(int o, int l ,int r, int L, int R) {
if (l >= L && r <= R) {
return mx[o];
}
pushdown(o);
int mid = (l+r) >> ;
int ans = -(<<);
if (L <= mid) ans = max(ans, query(lson, l, mid, L, R));
if (R > mid) ans = max(ans, query(rson, mid+, r, L, R));
pushup(o);
return ans;
} int QUERY(int x, int y, int n) {
if (x == y) return ;
int ans = -(<<);
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans = max(ans, query(, , n, dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if (x == y) return ans;
if (dep[x] > dep[y]) swap(x, y);
ans = max(ans, query(, , n, dfn[son[x]], dfn[y])); // 注意这里是son[x]
return ans;
} void init() {
idx = cntE = ;
memset(head, -, sizeof head);
memset(son, -, sizeof son);
} // 区间更新 点更新 区间查询
int main() {
int n, T;
scanf("%d",&T);
int cas = ;
while (T--) {
scanf("%d", &n); init();
int u, v, w;
for (int i = ; i < n; ++i) scanf("%d%d%d", &u, &v, &w), addedge(u, v, w, i);
dfs1(, , ); dfs2(, , ); build(, , n);
char op[];
while (~scanf("%s", op)) {
if (*op == 'D') break;
scanf("%d%d", &u, &v);
if (*op == 'Q') printf("%d\n", QUERY(u, v, n));
else if (*op == 'C') CHANGE(, , n, dfn[road[u]], v);
else NEGATE(u, v, n);
}
}
return ;
}
一组数据
/**
2
7
1 2 1
2 3 7
3 4 8
4 5 6
5 6 9
6 7 1
N 4 7
C 2 3
N 1 7
C 2 7
N 1 5
C 4 7
D
6
1 2 8
2 3 8
3 4 7
4 5 2
5 6 10
N 6 1
C 1 2
N 3 6
N 4 1
N 1 6
Q 2 6
D
Output:
8
1
7
8
10
-10
7
*/
POJ3237-Tree (树链剖分,线段树区间更新+点更新+区间查询)的更多相关文章
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- 【CF725G】Messages on a Tree 树链剖分+线段树
[CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...
- 【bzoj2325】[ZJOI2011]道馆之战 树链剖分+线段树区间合并
题目描述 给定一棵树,每个节点有上下两个格子,每个格子的状态为能走或不能走.m次操作,每次修改一个节点的状态,或询问:把一条路径上的所有格子拼起来形成一个宽度为2的长方形,从起点端两个格子的任意一个开 ...
- Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- Water Tree CodeForces 343D 树链剖分+线段树
Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
随机推荐
- ios开发之 MPMoviePlayerController 视频播放器
MPMoviePlayerController 与AVAudioPlayer有点类似,前者播放视频,后者播放音频,不过也有很大不同,MPMoviePlayerController 可以直接通过远程UR ...
- Ubuntu 安装mod_python配置Apache2
在Ubuntu上搭建Python运行环境,mod_python是不可少的(据说mod_swgi也是可以的,没有亲测).使用命令安装mod_python. 安装: apt-get install lib ...
- axis : java.lang.NoSuchMethodError
Hi friends,Iam getting the following error when deploying my app in jboss error.Iam new to axis .can ...
- ADO和DAO的区别
ADO(ACTIVEX DATA OBJECTS)应用层的数据访问接口ODBC 数据库驱动接口OLE DB 系统级数据访问接口DAO (DATA ACCESS OBJECTS) 对象的数据访问接口AD ...
- UVALive 4043 Ants(二分图完美匹配)
题意:每个蚁群有自己的食物源(苹果树),已知蚂蚁靠气味辨别行进方向,所以蚁群之间的行动轨迹不能重叠.现在给出坐标系中n个蚁群和n棵果树的坐标,两两配对,实现以上要求.输出的第 i 行表示第 i 个蚁群 ...
- UVA 11090 Going in Cycle!!(二分答案+判负环)
在加权有向图中求平均权值最小的回路. 一上手没有思路,看到“回路”,第一想法就是找连通分量,可又是加权图,没什么好思路,那就转换题意:由求回路权值->判负环,求最小值->常用二分答案. 二 ...
- [反汇编练习] 160个CrackMe之014
[反汇编练习] 160个CrackMe之014. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- RTP封装h264
网络抽象层单元类型 (NALU): NALU头由一个字节组成,它的语法如下: +---------------+ |0|1|2|3|4|5|6|7| +-+-+-+-+-+-+-+ ...
- Delphi 函数参数修饰中的var 、out和const
(1)var修饰符 添加var 是地址传递,会修改原有的变量 var s: string; begin S := 'Hello'; ChangeSVar(s); ShowMessage(S); e ...
- duilib corner属性的贴图技巧——让图片自动贴到控件的的某一边或者一角并自适应控件的大小
转载请说明原出处,谢谢~~ Duilib给控件贴图功能可以附带多个属性,各个属性的配合可以达到许多效果.以下是duilib支持的所有贴图属性: 贴图描述: Duilib的表现力丰富很大程度上得益于贴图 ...