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. ...
随机推荐
- Building Xcode iOS projects and creating *.ipa file from the command line
For our development process of iOS applications, we are using Jenkins set up on the Mac Mini Server, ...
- zoj 3785 What day is that day? (打表找规律)
题目 思路:比赛的时候有想过找循环节,但是,打表打错了. 后来,看着过了挺多人,就急了, 看了一下别人的时间 耗时都挺长的,就以为不是找规律, 没想到真是找规律,不过,这个题的数据可能挺大的. AC代 ...
- sql server2005内存过高释放方法
最近做了一个网站qq.115sou.com,在服务器中SQL Server占用内存非常高,加内存后,SQL Server又吃掉新加的内存,好像内存永远不够用一样,怎么办? 其实这并不一定是由于SQL ...
- js spin 加载动画(loading)
js spin 加载动画 最近做页面ajax加载是又用到loading动画,还好有一个spin.js 具体的包大家可以去http://fgnass.github.com/spin.js/下载, 如果想 ...
- HDU 1247 Hat’s Words
Hat’s Words Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- [Everyday Mathematics]20150108
设 $f$ 在 $(a,b)$ 上 $n+1$ 次可导, 且 $$\bex \ln\frac{f(b)+f'(b)+\cdots+f^{(n)}(b)}{f(a)+f'(a)+\cdots+f^{(n ...
- 【LeetCode 215】Kth Largest Element in an Array
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
- <转>Python 多线程的单cpu与cpu上的多线程的区别
你对Python 多线程有所了解的话.那么你对python 多线程在单cpu意义上的多线程与多cpu上的多线程有着本质的区别,如果你对Python 多线程的相关知识想有更多的了解,你就可以浏览我们的文 ...
- 《零成本实现Web自动化测试--基于Selenium》第二章 Selenium简介和基础
第一部分 Selenium简介 1.Selenium 组建 1.1 Selenium-IDE Selenium-IDC是开发Selenium测试案例的集成开发环境.它像FireFox插件一样的工作,支 ...
- 两段简单的JS代码防止SQL注入
1.URL地址防注入: //过滤URL非法SQL字符var sUrl=location.search.toLowerCase();var sQuery=sUrl.substring(sUrl.inde ...