题链:

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. C语言第一次博客作业 陈张鑫

    一,PTA实验作业 题目1.温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验代 ...

  2. c语言的第三次---单程循环结构

    一.PTA实验作业 题目1 1.代码 int N,i; double height; //height代表身高 char sex; //代表男女性别 scanf("%d",& ...

  3. 敏捷开发每日报告--day5

    1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285)  Git链接:https://github.com/WHUSE2017/C-team 2 ...

  4. 项目Beta冲刺Day5

    项目进展 李明皇 今天解决的进度 服务器端还未完善,所以无法进行联动调试.对页面样式和逻辑进行优化 明天安排 前后端联动调试 林翔 今天解决的进度 完成维护登录态,实现图片上传,微信开发工具上传图片不 ...

  5. 【iOS】swift-文字宽度的计算

    如图所示,需要sectionView的标题宽度可以动态变化 举例说明: 只需在tableView的代理方法 func tableView(tableView: UITableView, viewFor ...

  6. ResNet

     上图为单个模型 VGGNet, GoogleNet 都说明了深度对于神经网络的重要性. 文中在开始提出: 堆叠越多的层, 网络真的能学习的越好吗? 然后通过神经网络到达足够深度后出现的退化(deg ...

  7. 超绚丽CSS3多色彩发光立方体旋转动画

    CSS3添加了几个动画效果的属性,通过设置这些属性,可以做出一些简单的动画效果而不需要再去借助JavaScript.css3动画的属性主要分为三类:transform.transition以及anim ...

  8. 在bootstrap中让竖向排列的输入框水平排列

    在bootstrap中可以使用自带的样式标记来控制样式,但是同时可以利用最原始的css样式来解决达到需求 如下所示可以看出来两个inline-block就可以使得两个水平排列 block和inline ...

  9. Leetcode:Two Sum

    原题:https://leetcode.com/problems/two-sum/ 尝试了两种方法: 方法一: var twoSum = function(nums, target) { for(va ...

  10. restful架构风格设计准则(三)资源识别和资源设计

    读书笔记,原文链接:http://www.cnblogs.com/loveis715/p/4669091.html,感谢作者! restful风格的设计中,首先要识别系统中的资源,然后用HTTP规范表 ...