[POJ3237]Tree解题报告|树链剖分|边剖
关于边剖
之前做的大多是点剖,其实转换到边剖非常简单。
我的做法是每个点的点权记录其到父亲节点的边的边权。
只要solve的时候不要把最上面的点记录在内就可以了。
TreeDescription
You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:
CHANGE
i vChange the weight of the ith edge to v NEGATE
a bNegate the weight of every edge on the path from a to b QUERY
a bFind the maximum weight of edges on the path from a to b
这道题除了边剖之外另一个难点是处理NEGATE操作
将从a到b路径上的边权都取反
其实思考一下便知只要存mx和mn两个值然后反转的时候互换并取反就可以了
但是出现了问题,我以前用的向下传递不对了
因为反转操作的存在,当前的值很可能被子节点中本来并不优秀但是反转了之后能比当前点更好的点取代
然而传统的情况下当(tr[p].l=l)and(tr[p].r=r)的时候就停止了
这就导致了可能当前的状态并不是最优秀的
我们用一个push操作先向下传递一遍并刷新当前的值
保证当前p节点里的值都是真实存在的
在每个过程里都先执行一次push操作
时间复杂度看上去或许并不乐观,但是实际上标记为真的个数并不多
像这样特殊的操作就需要这种保证正确性的传递方式
以后遇到类似的题要多加思考
(树链剖分的题代码量真的很大啊QAQ
program poj3237;
const maxn=;maxm=;
var test,t,x,y,z,cnt,tt,n,m,j,i:longint;
son,size,link,belong,deep,v,pos:array[-..maxn]of longint;
ter,next,w:array[-..maxm]of longint;
fa:array[-..maxn,-..]of longint;
tr:array[-..*maxn]of record l,r,mx,mi:longint;wait,op:boolean;end;
ch:char; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end; procedure add(x,y,z:longint);
begin
inc(j);ter[j]:=y;next[j]:=link[x];link[x]:=j;w[j]:=z;
inc(j);ter[j]:=x;next[j]:=link[y];link[y]:=j;w[j]:=z;
end; procedure dfs1(p:longint);
var i,j:longint;
begin
size[p]:=;
for i:= to do
begin
if deep[p]<= << i then break;
fa[p][i]:=fa[fa[p][i-]][i-];
end;
j:=link[p];
while j<> do
begin
if deep[ter[j]]= then
begin
deep[ter[j]]:=deep[p]+;
fa[ter[j]][]:=p;
v[ter[j]]:=w[j];son[(j+) >> ]:=ter[j];
dfs1(ter[j]);
inc(size[p],size[ter[j]]);
end;
j:=next[j];
end;
end; procedure dfs2(p,chain:longint);
var j,k:longint;
begin
inc(cnt);pos[p]:=cnt;belong[p]:=chain;
k:=;
j:=link[p];
while j<> do
begin
if deep[ter[j]]>deep[p] then
if size[ter[j]]>size[k] then k:=ter[j];
j:=next[j];
end;
if k= then exit;
dfs2(k,chain);
j:=link[p];
while j<> do
begin
if (deep[ter[j]]>deep[p])and(ter[j]<>k) then dfs2(ter[j],ter[j]);
j:=next[j];
end;
end; procedure build(p,l,r:longint);
var mid:longint;
begin
tr[p].l:=l;tr[p].r:=r;tr[p].mx:=-maxlongint;tr[p].mi:=maxlongint;tr[p].wait:=false;tr[p].op:=false;
if l=r then exit;
mid:=(l+r) >> ;
build(p << ,l,mid);
build(p << +,mid+,r);
end; procedure push(p:longint);
var tem:longint;
begin
if tr[p].l=tr[p].r then exit;
if tr[p].wait then
begin
push(p << );push(p << +);
tr[p << ].mx:=max(tr[p].mx,tr[p << ].mx);tr[p << ].mi:=min(tr[p << ].mi,tr[p].mi);tr[p << ].wait:=true;
tr[p << +].mx:=max(tr[p].mx,tr[p << +].mx);tr[p << +].mi:=min(tr[p << +].mi,tr[p].mi);tr[p << +].wait:=true;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
tr[p].mi:=min(tr[p << ].mi,tr[p << +].mi);
tr[p].wait:=false;
end;
if tr[p].op then
begin
push(p << );push(p << +);
tem:=tr[p << ].mx;tr[p << ].mx:=-tr[p << ].mi;tr[p << ].mi:=-tem;tr[p << ].op:=true;
tem:=tr[p << +].mx;tr[p << +].mx:=-tr[p << +].mi;tr[p << +].mi:=-tem;tr[p << +].op:=true;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
tr[p].mi:=min(tr[p << ].mi,tr[p << +].mi);
tr[p].op:=false;
end;
end; procedure insert(p,l,r,ave:longint);
var mid,tem:longint;
begin
push(p);
if (tr[p].l=l)and(tr[p].r=r) then
begin
tr[p].mx:=ave;
tr[p].mi:=ave;
tr[p].wait:=true;
exit;
end;
mid:=(tr[p].l+tr[p].r) >> ;
if r<=mid then insert(p << ,l,r,ave) else
if l>mid then insert(p << +,l,r,ave) else
begin
insert(p << ,l,mid,ave);
insert(p << +,mid+,r,ave);
end;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
tr[p].mi:=min(tr[p << ].mi,tr[p << +].mi);
end; function lca(x,y:longint):longint;
var tem,i:longint;
begin
if deep[x]<deep[y] then
begin
tem:=x;x:=y;y:=tem;
end;
if deep[x]<>deep[y] then
begin
i:=trunc(ln(deep[x]-deep[y])/ln());
while deep[x]>deep[y] do
begin
while deep[x]-deep[y]>= << i do x:=fa[x][i];
dec(i);
end;
end;
if x=y then exit(x);
i:=trunc(ln(n)/ln());
while fa[x][]<>fa[y][] do
begin
while fa[x][i]<>fa[y][i] do
begin
x:=fa[x][i];y:=fa[y][i];
end;
dec(i);
end;
exit(fa[x][]);
end; function query(p,l,r:longint):longint;
var mid,tem:longint;
begin
push(p);
if (tr[p].l=l)and(tr[p].r=r) then exit(tr[p].mx);
mid:=(tr[p].l+tr[p].r) >> ;
if r<=mid then exit(query(p << ,l,r)) else
if l>mid then exit(query(p << +,l,r)) else
exit(max(query(p << ,l,mid),query(p << +,mid+,r)));
end; procedure dop(p,l,r:longint);
var mid,tem:longint;
begin
push(p);
if (tr[p].l=l)and(tr[p].r=r) then
begin
tem:=tr[p].mx;tr[p].mx:=-tr[p].mi;tr[p].mi:=-tem;
tr[p].op:=true;
exit;
end;
mid:=(tr[p].l+tr[p].r) >> ;
if r<=mid then dop(p << ,l,r) else
if l>mid then dop(p << +,l,r) else
begin
dop(p << ,l,mid);
dop(p << +,mid+,r);
end;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
tr[p].mi:=min(tr[p << ].mi,tr[p << +].mi);
end; function solve(x,y:longint):longint;
var mx:longint;
begin
mx:=-maxlongint;
while belong[x]<>belong[y] do
begin
mx:=max(mx,query(,pos[belong[x]],pos[x]));
x:=fa[belong[x]][];
end;
if x<>y then mx:=max(mx,query(,pos[y]+,pos[x]));
exit(mx);
end; procedure mend(x,y:longint);
begin
while belong[x]<>belong[y] do
begin
dop(,pos[belong[x]],pos[x]);
x:=fa[belong[x]][];
end;
if x<>y then dop(,pos[y]+,pos[x]);
end; begin
readln(test);
for tt:= to test do
begin
readln;
readln(n);j:=;
fillchar(link,sizeof(link),);
fillchar(next,sizeof(next),);
fillchar(deep,sizeof(deep),);
fillchar(fa,sizeof(fa),);
for i:= to n- do
begin
readln(x,y,z);
add(x,y,z);
end;
deep[]:=;dfs1();
cnt:=;dfs2(,);
build(,,n);
for i:= to n do insert(,pos[i],pos[i],v[i]);
read(ch);
while ch<>'D' do
begin
if ch='Q' then
begin
readln(ch,ch,ch,ch,x,y);
t:=lca(x,y);
writeln(max(solve(x,t),solve(y,t)));
end else
if ch='N' then
begin
readln(ch,ch,ch,ch,ch,x,y);
t:=lca(x,y);
mend(x,t);mend(y,t);
end else
begin
readln(ch,ch,ch,ch,ch,x,y);
insert(,pos[son[x]],pos[son[x]],y);
end;
read(ch);
end;
readln;
end;
end.
[POJ3237]Tree解题报告|树链剖分|边剖的更多相关文章
- [BZOJ2243][SDOI2011]染色 解题报告|树链剖分
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...
- [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分
树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...
- [jzoj 3175] 数树数 解题报告 (树链剖分)
interlinkage: https://jzoj.net/senior/#main/show/3175 description: 给定一棵N 个节点的树,标号从1~N.每个点有一个权值.要求维护两 ...
- [BZOJ1984]月下“毛景树”解题报告|树链剖分
Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树” ...
- Water Tree CodeForces 343D 树链剖分+线段树
Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...
- Codeforces Round #329 (Div. 2) D. Happy Tree Party LCA/树链剖分
D. Happy Tree Party Bogdan has a birthday today and mom gave him a tree consisting of n vertecie ...
- CF504E Misha and LCP on Tree 后缀自动机+树链剖分+倍增
求树上两条路径的 LCP (树上每个节点代表一个字符) 总共写+调了6个多小时,终于过了~ 绝对是我写过的最复杂的数据结构了 我们对这棵树进行轻重链剖分,然后把所有的重链分正串,反串插入到广义后缀自动 ...
- Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- CF 504E Misha and LCP on Tree——后缀数组+树链剖分
题目:http://codeforces.com/contest/504/problem/E 树链剖分,把重链都接起来,且把每条重链的另一种方向的也都接上,在这个 2*n 的序列上跑后缀数组. 对于询 ...
随机推荐
- Linux-Shell脚本编程-学习-1-Linux基本命令
在学习Linux-Shell脚本编程之前,我们需要学习一定的Linux基本命令,不然在后面学习Shell脚本编程的的时候,我们就呵呵了. 我学习所用的系统是Ubuntu 16.04版本 也没有什么规则 ...
- Qt QLabel 播放GIF动画
很久以前用过,不过慢慢的不用了,就慢慢的忘记了,今天拾起来,记录一下,以后用的时候可以翻一下 QLabel播放GIF动画其实很简单 第一步,需要包含头文件,Qt播放GIF动画,我使用的是QMovie类 ...
- 自动化测试学习之路--java 数组
数组的定义与为数组元素分配空间和赋值是分开进行的,称为动态初始化. 在数组定义的同时就为数组元素分配空间并赋值,称为静态初始化. 一维数组举例: //动态初始化 int[] intArr; intAr ...
- lua优化
前言 Lua是一门以其性能著称的脚本语言,被广泛应用在很多方面,尤其是游戏.像<魔兽世界>的插件,手机游戏<大掌门><神曲><迷失之地>等都是用Lua来 ...
- LeetCode - 1. Two Sum(8ms)
Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...
- BZOJ 4004 JLOI2015 装备购买 高斯消元+线性基
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4004 Description 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装 ...
- php+Mysql 页面登录代码
登录界面设置: <?php/** * Created by xx. * User: msi * Date: 2017/10/26 * Time: 18:12 *///session每次用之前都要 ...
- 【iOS开发】字典的快速赋值 setValuesForKeysWithDictionary
前言 在学习解析数据的时候,我们经常是这么写的:PersonModel.h文件中 @property (nonatomic,copy)NSString *name; @property (nonato ...
- C#中的Stack的Peek操作,曝出异常
我们在遍历一个栈的时候,有时候需要判断栈顶元素,用到了Peek元素,然后再用Pop元素,但是这个时候会出现一个逻辑错误, 当用Pop删除全部栈的元素时,再用Peek就会报错, InvalidOpera ...
- 关于C标准
关于C标准 1. 前言 本文从英文 C-FAQ (2004 年 7 月 3 日修订版) 翻译而来.本文的 中文版权为朱群英和孙云所有. 本文的内容可以自由用于个人目的,但 是不可以未经许可出版发行. ...