●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 【树链剖分】+【线段树】
<题目链接> 题目大意: 给定一棵树,该树带有边权,现在对该树进行三种操作: 一:改变指定编号边的边权: 二:对树上指定路径的边权全部取反: 三:查询树上指定路径的最大边权值. 解题分析: ...
随机推荐
- TRY
- 第十一条:谨慎的覆盖clone()方法
一个类要想实现克隆,需要实现Cloneable接口,表明这个类的对象具有克隆的功能. Cloneable接口是一个mixin接口,它里面并没有任何的抽象方法,类似的接口有Serializable接口, ...
- 201621123043 《Java程序设计》第2周学习总结
1.本周学习总结 使用jdk文档查阅函数功能及代码 用switch语句是在每个case中可能在第一行是sc.nextLine;来给回车赋值: 在使用循环的时候要注意循环返回的条件,否则陷入死循环可能会 ...
- Java 后端微信小程序支付demo (网上说的坑里面基本上都有)
Java 后端微信小程序支付 一.遇到的问题 1. 商户号该产品权限未开通,请前往商户平台>产品中心检查后重试 2.签名错误 3.已经调起微信统一下单接口,可以拿到预支付ID,但是前端支付的时候 ...
- PostgreSQL 客户端乱码问题
关于客户端和服务器端的乱码问题, POSTGRESQL字符集问题总结 总结的很详细, 特别棒. 这里让我头痛了很久的问题在于 终端 上字符编码的问题, 由于我的mbp上的 iterm2 的默认编码为 ...
- 03-移动端开发教程-CSS3新特性(下)
1. CSS3动画 1.1 过渡的缺点 transition的优点在于简单易用,但是它有几个很大的局限. transition需要事件触发,所以没法在网页加载时自动发生. transition是一次性 ...
- Python内置函数(62)——exec
英文文档: exec(object[, globals[, locals]]) This function supports dynamic execution of Python code. obj ...
- TCP/IP和HTTP协议代理
TCP/IP协议族 TCP/IP(传输控制协议/网际协议)是用于计算机通信的一个协议族. TCP/IP协议族包括诸如Internet协议(IP).地址解析协议(ARP).互联网控制信息协议(ICMP) ...
- 上传视频使用ffmpeg自动截取缩略图
上传视频之后,有的需要显示缩略图,而不是仅仅显示视频名称的列表,这时候就需要对上传的视频截取缩略图. 简单粗暴点,将以下代码作为工具类复制粘贴即可: package com.util; import ...
- Linux下安装Python3.x和第三方库
如果本机安装了python2,尽量不要管他,使用python3运行python脚本就好,因为可能有程序依赖目前的python2环境, 比如yum!!!!! 不要动现有的python2环境! 不要动现有 ...