题目链接: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标记)的更多相关文章

  1. 【Hihocoder 1167】 高等理论计算机科学 (树链的交,线段树或树状数组维护区间和)

    [题意] 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 少女幽香这几天正在学习高等理论计算机科学,然而她什么也没有学会,非常痛苦.所以她出去晃了一晃,做起了一些没什么意 ...

  2. [ZJOI2019]语言[树链的并、线段树合并]

    题意 题目链接 分析 考虑枚举每个点的答案,最后除以 2 即可. 可以与 \(u\) 构成合法点对 的集合 为所有经过了 \(u\) 的链的并.因为这些链两两有交,根据结论 "树上两条相交的 ...

  3. poj 3237 Tree(树链拆分)

    题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...

  4. poj 3237 Tree [LCA] (树链剖分)

    poj 3237 tree inline : 1. inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高. 2. 很明显,类 ...

  5. LOJ2269 [SDOI2017] 切树游戏 【FWT】【动态DP】【树链剖分】【线段树】

    题目分析: 好题.本来是一道好的非套路题,但是不凑巧的是当年有一位国家集训队员正好介绍了这个算法. 首先考虑静态的情况.这个的DP方程非常容易写出来. 接着可以注意到对于异或结果的计数可以看成一个FW ...

  6. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  7. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  8. BZOJ 2243:染色(树链剖分+区间合并线段树)

    [SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认 ...

  9. 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流

    [BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...

  10. 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组

    题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

随机推荐

  1. 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, ...

  2. zoj 3785 What day is that day? (打表找规律)

    题目 思路:比赛的时候有想过找循环节,但是,打表打错了. 后来,看着过了挺多人,就急了, 看了一下别人的时间 耗时都挺长的,就以为不是找规律, 没想到真是找规律,不过,这个题的数据可能挺大的. AC代 ...

  3. sql server2005内存过高释放方法

    最近做了一个网站qq.115sou.com,在服务器中SQL Server占用内存非常高,加内存后,SQL Server又吃掉新加的内存,好像内存永远不够用一样,怎么办? 其实这并不一定是由于SQL ...

  4. js spin 加载动画(loading)

    js spin 加载动画 最近做页面ajax加载是又用到loading动画,还好有一个spin.js 具体的包大家可以去http://fgnass.github.com/spin.js/下载, 如果想 ...

  5. HDU 1247 Hat’s Words

    Hat’s Words Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  6. [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 ...

  7. 【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 ...

  8. <转>Python 多线程的单cpu与cpu上的多线程的区别

    你对Python 多线程有所了解的话.那么你对python 多线程在单cpu意义上的多线程与多cpu上的多线程有着本质的区别,如果你对Python 多线程的相关知识想有更多的了解,你就可以浏览我们的文 ...

  9. 《零成本实现Web自动化测试--基于Selenium》第二章 Selenium简介和基础

    第一部分 Selenium简介 1.Selenium 组建 1.1 Selenium-IDE Selenium-IDC是开发Selenium测试案例的集成开发环境.它像FireFox插件一样的工作,支 ...

  10. 两段简单的JS代码防止SQL注入

    1.URL地址防注入: //过滤URL非法SQL字符var sUrl=location.search.toLowerCase();var sQuery=sUrl.substring(sUrl.inde ...