●POJ 3237 Tree
题链:
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的更多相关文章
- poj 3237 Tree [LCA] (树链剖分)
poj 3237 tree inline : 1. inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高. 2. 很明显,类 ...
- poj 3237 Tree(树链拆分)
题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...
- poj 3237 Tree 树链剖分
题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...
- POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)
题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...
- poj 3237 Tree(树链剖分,线段树)
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 7268 Accepted: 1969 Description ...
- POJ 3237 Tree (树链剖分)
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 2825 Accepted: 769 Description ...
- POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 12247 Accepted: 3151 Descriptio ...
- poj 3237 Tree 树链剖分+线段树
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- POJ 3237 Tree 【树链剖分】+【线段树】
<题目链接> 题目大意: 给定一棵树,该树带有边权,现在对该树进行三种操作: 一:改变指定编号边的边权: 二:对树上指定路径的边权全部取反: 三:查询树上指定路径的最大边权值. 解题分析: ...
随机推荐
- Json转model对象,model转json,解析json字符串
GitHub链接: https://github.com/mozhenhau/D3Json D3Json 通过swift的反射特性,把json数据转换为model对象,本类最主要是解决了其他一般jso ...
- oc中protocol、category和继承的区别
OC中protocol.category和继承的区别以前还是有点迷糊,面试的时候说的有点混乱,现在结合一些资料总结一下. 利用继承,多态是一个很好的保持"对扩展开放.对更改封闭"( ...
- Flask 蓝图(Blueprint)
蓝图使用起来就像应用当中的子应用一样,可以有自己的模板,静态目录,有自己的视图函数和URL规则,蓝图之间互相不影响.但是它们又属于应用中,可以共享应用的配置.对于大型应用来说,我们可以通过添加蓝图来扩 ...
- 【技巧】Java工程中的Debug信息分级输出接口及部署模式
也许本文的标题你们没咋看懂.但是,本文将带大家领略输出调试的威力. 灵感来源 说到灵感,其实是源于笔者在修复服务器的ssh故障时的一个发现. 这个学期初,同袍(容我来一波广告产品页面,同袍官网)原服务 ...
- dede使用心得
Question one: 最近做了一些视频教程传到优酷网站上,但我想引入这些视频教程到我的网站,在发表时我发现织梦CMS自带的编辑器又不直接支持优酷等视频网站的引用.所以为了方便教程的发布,特意在网 ...
- C# HttpClient设置cookies的两种办法 (转发)
一般有两种办法 第一种handler.UseCookies=true(默认为true),默认的会自己带上cookies,例如 var handler = new HttpClientHandler() ...
- 第1章 什么是TCP-IP
第1章 什么是TCP-IP 什么是网络 网络是计算机或类似计算机的设备之间通过常用传输介质进行通信的集合.通常情况下,传输介质是绝缘的金属导线, 它用来在计算机之间携带电脉冲,介质也可以是电话线,甚至 ...
- “认证发布”和“获取展示”,如何在 SharePoint 中正确使用 RSS Feed。
在我们进行的日常工作中,是由一部分信息需要 Share 给其他人或者组织的.SharePoint 虽然支持在某个 Site Collection 中互通信息,但是跨 Site Collection 的 ...
- Linux知识积累(1)awk的使用方法
参见:http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html 简介 awk是一个强大的文本分析工具,相对于grep的查找,se ...
- OAuth2.0学习(1-8) 授权方式五之Access_Token令牌过期更新
OAuth2.0的Access_Token令牌过期更新 如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌"申请一个新的访问令牌. 客户端发 ...