POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)
题目链接:http://poj.org/problem?id=3237
一棵有边权的树,有3种操作。
树链剖分+线段树lazy标记。lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每次更新异或1就可以。
熟悉线段树成段更新就很简单了,最初姿势不对一直wa,还是没有彻底理解lazy标记啊。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1e4 + ;
struct EDGE {
int next , to , cost;
}edge[MAXN << ];
int head[MAXN] , tot;
int par[MAXN] , size[MAXN] , son[MAXN] , dep[MAXN];
int top[MAXN] , id[MAXN] , cnt;
int from[MAXN] , to[MAXN] , cost[MAXN]; void init() {
tot = cnt = ;
memset(head , - , sizeof(head));
} inline void add(int u , int v , int cost) {
edge[tot].next = head[u];
edge[tot].to = v;
head[u] = tot++;
} void dfs1(int u , int p , int d) {
par[u] = p , size[u] = , son[u] = u , dep[u] = d;
for(int i = head[u] ; ~i ; i = edge[i].next) {
int v = edge[i].to;
if(v == p)
continue;
dfs1(v , u , d + );
if(size[v] >= size[son[u]])
son[u] = v;
size[u] += size[v];
}
} void dfs2(int u , int p , int t) {
top[u] = t , id[u] = ++cnt;
if(son[u] != u)
dfs2(son[u] , u , t);
for(int i = head[u] ; ~i ; i = edge[i].next) {
int v = edge[i].to;
if(v == p || v == son[u])
continue;
dfs2(v , u , v);
}
} struct SegTree {
int l , r , Max , lazy , Min; //lazy变量0表示无更新 1表示有更新
}T[MAXN << ]; void build(int p , int l , int r) {
int mid = (l + r) >> ;
T[p].l = l , T[p].r = r , T[p].lazy = ;
if(l == r) {
return ;
}
build(p << , l , mid);
build((p << )| , mid + , r);
} void pushup(int p) {
if(T[p].lazy) {
int ls = p << , rs = (p << )|;
T[ls].lazy ^= ;
T[rs].lazy ^= ; int temp;
temp = T[ls].Max;
T[ls].Max = -T[ls].Min;
T[ls].Min = -temp; temp = T[rs].Max;
T[rs].Max = -T[rs].Min;
T[rs].Min = -temp;
T[p].lazy = ;
}
}
//更新操作就是 将原来的Max变成-Min ,Min变成-Max
void updata(int p , int l , int r , int flag) {
int mid = (T[p].r + T[p].l) >> ;
if(T[p].l == l && T[p].r == r) {
T[p].lazy ^= flag;
int temp = T[p].Max;
T[p].Max = -T[p].Min;
T[p].Min = -temp;
return ;
}
pushup(p);
if(r <= mid) {
updata(p << , l , r , flag);
}
else if(l > mid) {
updata((p << )| , l , r , flag);
}
else {
updata(p << , l , mid , flag);
updata((p << )| , mid + , r , flag);
}
T[p].Max = max(T[p << ].Max , T[(p << )|].Max);
T[p].Min = min(T[p << ].Min , T[(p << )|].Min);
} int query(int p , int l , int r) {
int mid = (T[p].l + T[p].r) >> ;
if(T[p].l == l && T[p].r == r) {
return T[p].Max;
}
pushup(p);
if(r <= mid) {
return query(p << , l , r);
}
else if(l > mid) {
return query((p << )| , l , r);
}
else {
return max(query(p << , l , mid) , query((p << )| , mid + , r));
}
} void updata_pos(int p , int pos , int num) {
int mid = (T[p].l + T[p].r) >> ;
if(T[p].l == T[p].r && T[p].l == pos) {
T[p].Max = T[p].Min = num;
T[p].lazy = ;
return ;
}
pushup(p);
if(pos <= mid) {
updata_pos(p << , pos , num);
}
else {
updata_pos((p << )| , pos , num);
}
T[p].Max = max(T[p << ].Max , T[(p << )|].Max);
T[p].Min = min(T[p << ].Min , T[(p << )|].Min);
} int find_max(int u , int v) {
int fu = top[u] , fv = top[v] , Max = -;
while(fv != fu) {
if(dep[fu] > dep[fv]) {
Max = max(Max , query( , id[fu] , id[u]));
u = par[fu];
fu = top[u];
}
else {
Max = max(Max , query( , id[fv] , id[v]));
v = par[fv];
fv = top[v];
}
}
if(v == u)
return Max;
else if(dep[u] > dep[v])
return max(Max , query( , id[son[v]] , id[u]));
else
return max(Max , query( , id[son[u]] , id[v]));
} void change(int u , int v) {
int fu = top[u] , fv = top[v];
while(fu != fv) {
if(dep[fu] > dep[fv]) {
updata( , id[fu] , id[u] , );
u = par[fu];
fu = top[u];
}
else {
updata( , id[fv] , id[v] , );
v = par[fv];
fv = top[v];
}
}
if(v == u)
return ;
else if(dep[u] > dep[v])
updata( , id[son[v]] , id[u] , );
else
updata( , id[son[u]] , id[v] , );
} int main()
{
int t, n;
scanf("%d", &t);
while(t--) {
init();
scanf("%d" , &n);
for(int i = ; i < n ; ++i) {
scanf("%d %d %d" , from + i , to + i , cost + i);
add(from[i] , to[i] , cost[i]);
add(to[i] , from[i] , cost[i]);
}
dfs1( , , );
dfs2( , , );
build( , , cnt);
for(int i = ; i < n ; ++i) {
if(dep[from[i]] < dep[to[i]])
swap(from[i] , to[i]);
updata_pos( , id[from[i]] , cost[i]);
}
char q[];
int l , r;
while(scanf("%s" , q) && q[] != 'D') {
scanf("%d %d" , &l , &r);
if(q[] == 'Q') {
printf("%d\n" , find_max(l , r));
}
else if(q[] == 'N') {
change(l , r);
}
else {
updata_pos( , id[from[l]] , r);
}
}
}
return ;
}
POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)的更多相关文章
- 【Hihocoder 1167】 高等理论计算机科学 (树链的交,线段树或树状数组维护区间和)
[题意] 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 少女幽香这几天正在学习高等理论计算机科学,然而她什么也没有学会,非常痛苦.所以她出去晃了一晃,做起了一些没什么意 ...
- [ZJOI2019]语言[树链的并、线段树合并]
题意 题目链接 分析 考虑枚举每个点的答案,最后除以 2 即可. 可以与 \(u\) 构成合法点对 的集合 为所有经过了 \(u\) 的链的并.因为这些链两两有交,根据结论 "树上两条相交的 ...
- poj 3237 Tree(树链拆分)
题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...
- poj 3237 Tree [LCA] (树链剖分)
poj 3237 tree inline : 1. inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高. 2. 很明显,类 ...
- LOJ2269 [SDOI2017] 切树游戏 【FWT】【动态DP】【树链剖分】【线段树】
题目分析: 好题.本来是一道好的非套路题,但是不凑巧的是当年有一位国家集训队员正好介绍了这个算法. 首先考虑静态的情况.这个的DP方程非常容易写出来. 接着可以注意到对于异或结果的计数可以看成一个FW ...
- BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
- BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- BZOJ 2243:染色(树链剖分+区间合并线段树)
[SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认 ...
- 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流
[BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...
- 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组
题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...
随机推荐
- UVa 1515 (最小割) Pool construction
题意: 输入一个字符矩阵,'.'代表洞,'#'代表草地.可以把草改成洞花费为d,或者把洞改成草花费为f,最后还要在草和洞之间修围栏花费为b. 但要保证最外一圈是草,求最小费用. 分析: 还不是特别理解 ...
- UVa 1025 (动态规划) A Spy in the Metro
题意: 有线性的n个车站,从左到右编号分别为1~n.有M1辆车从第一站开始向右开,有M2辆车从第二站开始向左开.在0时刻主人公从第1站出发,要在T时刻回见车站n 的一个间谍(忽略主人公的换乘时间).输 ...
- hdu 4635 Strongly connected(强连通)
考强连通缩点,算模板题吧,比赛的时候又想多了,大概是不自信吧,才开始认真搞图论,把题目想复杂了. 题意就是给你任意图,保证是simple directed graph,问最多加多少条边能使图仍然是si ...
- 浅析Java中HashMap的实现
概述 HashMap是一个散列表,是基于拉链法实现的.这个类继承了Map接口,Map接口提供了所有的哈希操作,比如set().put().remove()等,并且允许操作的键值对为null.HashM ...
- RTP协议分析
目录(?)[-] 第1章 RTP概述 RTP是什么 RTP的应用环境 相关概念 流媒体 第2章 RTP详解 RTP的协议层次 传输层的子层 应用层的一部分 RTP的封装 RTCP的 ...
- 【LCS,LIS】最长公共子序列、单调递增最长子序列
单调递增最长子序列 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 求一个字符串的最长递增子序列的长度如:dabdbf最长递增子序列就是abdf,长度为4 输入 ...
- 【转】cocos2d-x与ios内存管理分析(在游戏中减少内存压力)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=281 注:自己以前也写过coco ...
- Eclipse小技巧<一>
Eclipse是一款特别好用的开源开发工具,基于插件的特性使其能够进行各种语言的开发.非常喜欢eclipse里的编码风格,感觉这个开发工具十分灵活,又有很多开发的小技巧能够提高开发效率,每次学到一个t ...
- 锋利的jQuery读书笔记---jQuery中操作DOM
一般来说,DOM的操作分为3个方面,即DOM Core.HTML-DOM和CSS-DOM jQuery中的DOM操作主要包括以下种类: 查找节点 查找元素节点 查找属性节点 创建节点 创建元素节点 创 ...
- #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)宏的运行机理:1. ( (TYPE *)0 ) 将零转型为TY ...