关于边剖

  之前做的大多是点剖,其实转换到边剖非常简单。

  我的做法是每个点的点权记录其到父亲节点的边的边权。

  只要solve的时候不要把最上面的点记录在内就可以了。


Tree

Description

  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 v Change the weight of the ith edge to v
NEGATE a b Negate the weight of every edge on the path from a to b
QUERY a b Find 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解题报告|树链剖分|边剖的更多相关文章

  1. [BZOJ2243][SDOI2011]染色 解题报告|树链剖分

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...

  2. [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分

    树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...

  3. [jzoj 3175] 数树数 解题报告 (树链剖分)

    interlinkage: https://jzoj.net/senior/#main/show/3175 description: 给定一棵N 个节点的树,标号从1~N.每个点有一个权值.要求维护两 ...

  4. [BZOJ1984]月下“毛景树”解题报告|树链剖分

    Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树” ...

  5. Water Tree CodeForces 343D 树链剖分+线段树

    Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...

  6. 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 ...

  7. CF504E Misha and LCP on Tree 后缀自动机+树链剖分+倍增

    求树上两条路径的 LCP (树上每个节点代表一个字符) 总共写+调了6个多小时,终于过了~ 绝对是我写过的最复杂的数据结构了 我们对这棵树进行轻重链剖分,然后把所有的重链分正串,反串插入到广义后缀自动 ...

  8. 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, ...

  9. CF 504E Misha and LCP on Tree——后缀数组+树链剖分

    题目:http://codeforces.com/contest/504/problem/E 树链剖分,把重链都接起来,且把每条重链的另一种方向的也都接上,在这个 2*n 的序列上跑后缀数组. 对于询 ...

随机推荐

  1. 圣思源Java视频36节练习源码分享(自己的190+行代码对比老师的39行代码)

    题目: * 随机生成50个数字(整数),每个数字范围是[10,50],统计每个数字出现的次数 * 以及出现次数最多的数字与它的个数,最后将每个数字及其出现次数打印出来, * 如果某个数字出现次数为0, ...

  2. java通过句柄访问对象

    在Java里,任何东西都可看作对象.尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“句柄”(Handle),有的人将其称作一个“引用”,甚至一个“指针”. 主类型的数据成员可直接初始化, ...

  3. Qt Qwdget 汽车仪表知识点拆解1 速度表示

    先贴上效果图,注意,没有写逻辑,所以这些都是乱动的 这里线主要说一下中间显示速度的显示制作的方式,在这里,自己专门写了一个数字的仪表 考虑的一般的汽车是没有办法把瞬时速度提升到四位数的,所以我这里就放 ...

  4. Ubuntu下使用Git_1

    这里小小的记录一下我在Ubuntu下使用版本控制工具Git的过程.在学习使用Git的时候,我发现了一个很好的网站,这里分享一下,大家共同学习. 猴子都能懂的Git入门 http://git.wiki. ...

  5. Python 3 学习笔记之——面向对象

    1. 类的介绍 类(Class) 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例,类是对象的抽象. 方法:类中定义的函数. 类变量:类变量在整个实 ...

  6. Spring定时器调用Hibernate方法无法获得SessionFactory的解决办法

    由于在Spring定时器中无法通过注解的方式获取bean,因此需要通过原生的方式获取.获取session的方式如下: WebApplicationContext wac = ContextLoader ...

  7. R6的压力测试

    VersionCode:{102} VersionName:{1.0.2}

  8. 基于JWT的无状态分布式授权【本文摘自智车芯官网】

    简介 JWT是一种用于HTTP交互双方之间传递安全信息的简洁的.安全的表述性声明规范.JWT作为一个开发的标准,它定义了一种简洁的,自包含的方法用于通信双发之间以JSON形式安全传递.且因为数字证书的 ...

  9. js定时器实现图片轮播

    效果展示如下: setInterval(moverleft,3000);定时器设置为3秒,而且实现图片下方的小圆点序号跟图片对应,点击小圆点也能切换图片. 代码如下: <!DOCTYPE htm ...

  10. HDU 2135 Rolling table

    http://acm.hdu.edu.cn/showproblem.php?pid=2135 Problem Description After the 32nd ACM/ICPC regional ...