[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 的序列上跑后缀数组. 对于询 ...
随机推荐
- NB-IOT的键值对
1. 关于NB-IOT的软件开发,有一个功能,NB收到数据的时候可以唤醒处于低功耗下的MCU. 2. 2个键值对可以配置这个功能.使用键值对的方式. 3. 遇到的第一个问题,<config> ...
- Android TV 开发(3)
本文来自网易云社区 作者:孙有军 <LinearLayout android:id="@+id/input_num_line_3" and ...
- android中的AIDL学习笔记
一.定义 AIDL是用来解决进程间通信的(一般有四种方式:Activity.Service.ContentProvider.Broadcast Receiver),两个进程间无法直接通信,所以要用AI ...
- java 泛型类转型
public class NeedCasting { @SuppressWarnings("unchecked") public void f(String[] args)thro ...
- 第六篇 常用请求协议之post put patch 总结
[转]https://blog.csdn.net/sshfl_csdn 感谢愿意总结分享的人,thanks idempotent 幂等的 如果一个方法重复执行多次,产生的效果是一样的,那就是i ...
- 软件工程项目组Z.XML会议记录 2013/11/20
软件工程项目组Z.XML会议记录 [例会时间]2013年11月20日星期三21:00-22:00 [例会形式]小组讨论 [例会地点]学生公寓3号楼会客厅 [例会主持]李孟 [会议记录]李孟 会议整体流 ...
- MySQL初始4--去重
更新表中的字段: update 表名 set 字段=新值,… where 条件: UPDATE语法可以用新值更新原有表行中的各列.SET子句指示要修改哪些列和要给予哪些值.WHERE子句指定应更新哪些 ...
- 关于org.springframework.web.filter.CharacterEncodingFilter的学习
介绍 org.springframework.web.filter.CharacterEncodingFilter 这是一个过滤器,是Spring在web请求中定义request和response的编 ...
- 201621123033 《Java程序设计》第13周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多个用户通过网 ...
- PS制作圆角透明图片
方法一:利用“魔术棒橡皮工具”. 1. 点击“圆角矩形工具”,然后选中打开的背景图片,选中即可. 2.然后,按住“ctrl+enter”,所选边框变为虚线框,然后点击“ctrl+shift+i”反选( ...