关于边剖

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

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

  只要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. SharePoint显示错误信息

         在SharePoint项目中,一般如果发生错误,SharePoint会弹出它自定义的报错页面,一般就显示"Something went wrong",如果光是看这一句话, ...

  2. C++学习011-常用内存分配及释放函数

    C++用有多种方法来分配及释放内存,下面是一些经常使用的内存分配及释放函数 现在我还是一个技术小白,一般用到也指示 new+delete 和 malloc和free 其他的也是在学习中看到,下面的文字 ...

  3. 第二篇 Fiddler配置_浏览器&手机

    什么是Fiddler? 网络项目的开发和测试中,Fiddler是强大的抓包工具,它的原理是以web代理服务器的形式进行工作的 ,可以说是非常常用的手头工具了,本文就Fiddler使用和配置进行说明. ...

  4. Struts2(三.用户登录状态显示及Struts2标签)

    1.编写main.jsp /WebContent/main.jsp 之前用户登录时已把用户存入session <%@ page language="java" content ...

  5. c++知识点总结--函数模板

    通用函数可变参模板 用于处理不限定参数的函数 showall(){//空函数,接口,最后结束递归 } template<typename T,typename... Args> void ...

  6. DFS(7)——poj1011Sticks

    一.题目回顾 题目链接:Sticks 题意:给出一定数量的小木棒的长度,它是由等长的若干木棒随意砍断所得到的.对于给定的一组小木棒,请求出原始木棒的最小长度. 二.解题思路 DFS+剪枝 本题剪枝不到 ...

  7. 线段树——hdu1166敌兵布阵

    一.题目回顾 题目链接:敌兵布阵 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个 ...

  8. 提高python执行效率的方法

    python上手很容易,但是在使用过程中,怎么才能使效率变高呢? 下面说一下提高python执行效率的方法,这里只是说一点,python在引入模块过程中提高效率的方法. 例如: 1.我们要使用os模块 ...

  9. 福大软工1816:Alpha(2/10)

    Alpha 冲刺 (2/10) 队名:第三视角 组长博客链接 本次作业链接 团队部分 团队燃尽图 工作情况汇报 张扬(组长) 过去两天完成了哪些任务: 文字/口头描述: 1.学习qqbot库: 2.实 ...

  10. 【EasyNetQ】- 使用Future Publish调度事件

    许多业务流程要求在将来某个日期安排事件.例如,在与客户进行初次销售联系后,我们可能希望在将来的某个时间安排跟进电话.EasyNetQ可以通过其Future Publish功能帮助您实现此功能.例如,这 ...