题链:

http://poj.org/problem?id=3237

题解:

LCT

说一说如何完成询问操作就好了(把一条链的边权变成相反数的操作可以类比着来):

首先明确一下,我们把边权下放到点上。

(由于不存在合并,即不需要MovetoRoot操作,也就是说不需要改变树的形态,让它成为以1为根的有根树即可)

对于询问的a,b之间链上的最大值,

我们首先调用Access(b)函数,让b和根之间形成一条重链,

然后对x=a执行类似Access的过程,直到某一刻发现fa[x]==0时,

则表明现在的x是在b到根的路径上,或者说,此时的x点是a,b的最近公共祖先lca,

所以直接返回y子树和ch[x][1]子树的最大值就好了。

建议结合代码理解:

int Query(int x,int y){
static int ret; Access(y);
for(y=0;x;y=x,x=fa[x]){
Splay(x);
if(fa[x]) ch[x][1]=y;
else ret=max(maxi[y],maxi[ch[x][1]]);
Pushup(x);
}
return ret;
}

其他就没什么好说的了,都比较常规。

代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 10050
#define INF 0x3f3f3f3f
using namespace std;
struct Edge{
int to[MAXN*2],nxt[MAXN*2],val[MAXN*2],head[MAXN],ent;
void Reset(){ent=2; memset(head,0,sizeof(head));}
void Adde(int u,int v,int w){
to[ent]=v; val[ent]=w;
nxt[ent]=head[u]; head[u]=ent++;
}
}E;
int belong[MAXN];
int Case,N;
struct LCT{
int ch[MAXN][2],fa[MAXN];
int maxi[MAXN],mini[MAXN],w[MAXN],lazy[MAXN];
void Reset(){
memset(ch,0,sizeof(ch));
memset(lazy,0,sizeof(lazy));
maxi[0]=-INF; mini[0]=INF;
}
bool Which(int x){return ch[fa[x]][1]==x;}
bool Isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void Pushup(int x){
maxi[x]=max(w[x],max(maxi[ch[x][0]],maxi[ch[x][1]]));
mini[x]=min(w[x],min(mini[ch[x][0]],mini[ch[x][1]]));
}
void Opposite(int x){ w[x]*=-1; maxi[x]*=-1; mini[x]*=-1;
swap(maxi[x],mini[x]);
lazy[x]^=1;
}
void Pushdown(int x){
if(!Isroot(x)) Pushdown(fa[x]);
if(!lazy[x]) return;
Opposite(ch[x][0]); Opposite(ch[x][1]);
lazy[x]^=1;
}
void Rotate(int x){
static int y,z,l1,l2;
y=fa[x]; z=fa[y];
l1=Which(x); l2=Which(y); fa[x]=z;
if(!Isroot(y)) ch[z][l2]=x;
fa[ch[x][l1^1]]=y; fa[y]=x;
ch[y][l1]=ch[x][l1^1]; ch[x][l1^1]=y;
Pushup(y);
}
void Splay(int x){
static int y; Pushdown(x);
for(;y=fa[x],!Isroot(x);Rotate(x))
if(!Isroot(y)) Rotate(Which(x)==Which(y)?y:x);
Pushup(x);
}
void Access(int x){
static int y;
for(y=0;x;y=x,x=fa[x])
Splay(x),ch[x][1]=y,Pushup(x);
}
void Change(int i,int v){
static int x; x=belong[i];
Splay(x); w[x]=v; Pushup(x);
}
void Negate(int x,int y){
Access(y);
for(y=0;x;y=x,x=fa[x]){
Splay(x);
if(fa[x]) ch[x][1]=y;
else Opposite(y),Opposite(ch[x][1]);
Pushup(x);
}
}
int Query(int x,int y){
static int ret; Access(y);
for(y=0;x;y=x,x=fa[x]){
Splay(x);
if(fa[x]) ch[x][1]=y;
else ret=max(maxi[y],maxi[ch[x][1]]);
Pushup(x);
}
return ret;
}
}DT;
void DFS(int u,int dad){
DT.fa[u]=dad;
for(int i=E.head[u];i;i=E.nxt[i]){
int v=E.to[i]; if(v==dad) continue;
belong[i>>1]=v; DT.maxi[v]=DT.mini[v]=DT.w[v]=E.val[i];
DFS(v,u);
}
}
int main(){
int a,b,c; char cmd[10];
for(scanf("%d",&Case);Case;Case--){
DT.Reset(); E.Reset();
scanf("%d",&N);
for(int i=1;i<N;i++){
scanf("%d%d%d",&a,&b,&c);
E.Adde(a,b,c); E.Adde(b,a,c);
}
DFS(1,0);
while(~scanf("%s",cmd)){
if(cmd[0]=='D') break;
scanf("%d%d",&a,&b);
if(cmd[0]=='Q') printf("%d\n",DT.Query(a,b));
else if(cmd[0]=='C') DT.Change(a,b);
else DT.Negate(a,b);
}
}
return 0;
}

  

●POJ 3237 Tree的更多相关文章

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

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

  2. poj 3237 Tree(树链拆分)

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

  3. poj 3237 Tree 树链剖分

    题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...

  4. POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

    题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...

  5. poj 3237 Tree(树链剖分,线段树)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7268   Accepted: 1969 Description ...

  6. POJ 3237 Tree (树链剖分)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 2825   Accepted: 769 Description ...

  7. POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12247   Accepted: 3151 Descriptio ...

  8. poj 3237 Tree 树链剖分+线段树

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  9. POJ 3237 Tree 【树链剖分】+【线段树】

    <题目链接> 题目大意: 给定一棵树,该树带有边权,现在对该树进行三种操作: 一:改变指定编号边的边权: 二:对树上指定路径的边权全部取反: 三:查询树上指定路径的最大边权值. 解题分析: ...

随机推荐

  1. 201621123031 《Java程序设计》第9周学习总结

    作业09-集合与泛型 1.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 一.泛型的基本概念 泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Paramet ...

  2. SCOI2010 序列操作

    2421 序列操作 http://codevs.cn/problem/2421/ 2010年省队选拔赛四川   题目描述 Description lxhgww最近收到了一个01序列,序列里面包含了n个 ...

  3. 数据恢复培训资料:BMP文件详解

    BMP是一种与硬件设备无关的图像文件格式,使用非常广.它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BblP文件所占用的空间很大.BMP文件的图像深度可选lbit.4bit.8 ...

  4. 09-移动端开发教程-Sass入门

    1. 引言 CSS3之前的CSS都大都是枚举属性样式,而编程语言强大的变量.函数.循环.分支等功能基本都不能在CSS中使用,让CSS的编程黯淡无光,Sass就是一种增强CSS编程的扩展语言(CSS4也 ...

  5. HTML 字符集

    在 HTML 中,正确的字符编码是什么?   HTML5 中默认的字符编码是 UTF-8. 这并非总是如此.早期网络的字符编码是 ASCII 码.后来,从 HTML 2.0 到 HTML 4.01,I ...

  6. 【bug清除】Surface Pro系列使用Drawboard PDF出现手写偏移、卡顿、延迟现象的解决方式

    最近自己新买的New Surface Pro在使用Drawboard PDF时,出现了性能问题,即笔迹延迟偏移,卡顿的问题. 排查驱动问题之后,确认解决方案如下: 将Surface的电池调到性能模式, ...

  7. JAVA_SE基础——63.String类的常用方法

    获取方法int length()  获取字符串的长度char charAt(int index) 获取特定位置的字符 (角标越界)int indexOf(String str) 查找子串第一次出现的索 ...

  8. js解决IE8不支持html5,css3的问题(respond.js 的使用注意)

    IE8.0及以下不支持html5,css3的解析.目前为止IE8以下的版本使用率在10%左右,网站还是有必要兼容的. 1,在你的所有css最后判断引入两个js文件. html5.js  是用来让ie8 ...

  9. 剑指offer-反转单词顺序列

    题目描述 牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上.同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思.例如,"st ...

  10. 常用cmd代码片段及.net core打包脚本分享

    bat基础命令 注释:rem 注释~~ 输出:echo hello world 接收用户输入:%1 %2,第n个变量就用%n表示 当前脚本路径:%~dp0 当前目录路径:%cd% 设置变量:set c ...