[POJ3237]Tree解题报告|树链剖分|边剖

关于边剖

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

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

  只要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

  1 program poj3237;
  2 const maxn=10010;maxm=20010;
  3 var test,t,x,y,z,cnt,tt,n,m,j,i:longint;
  4     son,size,link,belong,deep,v,pos:array[-1..maxn]of longint;
  5     ter,next,w:array[-1..maxm]of longint;
  6     fa:array[-1..maxn,-1..20]of longint;
  7     tr:array[-1..5*maxn]of record l,r,mx,mi:longint;wait,op:boolean;end;
  8     ch:char;
  9
 10 function max(a,b:longint):longint;
 11 begin
 12     if a>b then exit(a) else exit(b);
 13 end;
 14
 15 function min(a,b:longint):longint;
 16 begin
 17     if a<b then exit(a) else exit(b);
 18 end;
 19
 20 procedure add(x,y,z:longint);
 21 begin
 22     inc(j);ter[j]:=y;next[j]:=link[x];link[x]:=j;w[j]:=z;
 23     inc(j);ter[j]:=x;next[j]:=link[y];link[y]:=j;w[j]:=z;
 24 end;
 25
 26 procedure dfs1(p:longint);
 27 var i,j:longint;
 28 begin
 29     size[p]:=1;
 30     for i:=1 to 15 do
 31     begin
 32         if deep[p]<=1 << i then break;
 33         fa[p][i]:=fa[fa[p][i-1]][i-1];
 34     end;
 35     j:=link[p];
 36     while j<>0 do
 37     begin
 38         if deep[ter[j]]=0 then
 39         begin
 40             deep[ter[j]]:=deep[p]+1;
 41             fa[ter[j]][0]:=p;
 42             v[ter[j]]:=w[j];son[(j+1) >> 1]:=ter[j];
 43             dfs1(ter[j]);
 44             inc(size[p],size[ter[j]]);
 45         end;
 46         j:=next[j];
 47     end;
 48 end;
 49
 50 procedure dfs2(p,chain:longint);
 51 var j,k:longint;
 52 begin
 53     inc(cnt);pos[p]:=cnt;belong[p]:=chain;
 54     k:=0;
 55     j:=link[p];
 56     while j<>0 do
 57     begin
 58         if deep[ter[j]]>deep[p] then
 59             if size[ter[j]]>size[k] then k:=ter[j];
 60         j:=next[j];
 61     end;
 62     if k=0 then exit;
 63     dfs2(k,chain);
 64     j:=link[p];
 65     while j<>0 do
 66     begin
 67         if (deep[ter[j]]>deep[p])and(ter[j]<>k) then dfs2(ter[j],ter[j]);
 68         j:=next[j];
 69     end;
 70 end;
 71
 72 procedure build(p,l,r:longint);
 73 var mid:longint;
 74 begin
 75     tr[p].l:=l;tr[p].r:=r;tr[p].mx:=-maxlongint;tr[p].mi:=maxlongint;tr[p].wait:=false;tr[p].op:=false;
 76     if l=r then exit;
 77     mid:=(l+r) >> 1;
 78     build(p << 1,l,mid);
 79     build(p << 1+1,mid+1,r);
 80 end;
 81
 82 procedure push(p:longint);
 83 var tem:longint;
 84 begin
 85     if tr[p].l=tr[p].r then exit;
 86     if tr[p].wait then
 87     begin
 88         push(p << 1);push(p << 1+1);
 89         tr[p << 1].mx:=max(tr[p].mx,tr[p << 1].mx);tr[p << 1].mi:=min(tr[p << 1].mi,tr[p].mi);tr[p << 1].wait:=true;
 90         tr[p << 1+1].mx:=max(tr[p].mx,tr[p << 1+1].mx);tr[p << 1+1].mi:=min(tr[p << 1+1].mi,tr[p].mi);tr[p << 1+1].wait:=true;
 91         tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
 92         tr[p].mi:=min(tr[p << 1].mi,tr[p << 1+1].mi);
 93         tr[p].wait:=false;
 94     end;
 95     if tr[p].op then
 96     begin
 97         push(p << 1);push(p << 1+1);
 98         tem:=tr[p << 1].mx;tr[p << 1].mx:=-tr[p << 1].mi;tr[p << 1].mi:=-tem;tr[p << 1].op:=true;
 99         tem:=tr[p << 1+1].mx;tr[p << 1+1].mx:=-tr[p << 1+1].mi;tr[p << 1+1].mi:=-tem;tr[p << 1+1].op:=true;
100         tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
101         tr[p].mi:=min(tr[p << 1].mi,tr[p << 1+1].mi);
102         tr[p].op:=false;
103     end;
104 end;
105
106 procedure insert(p,l,r,ave:longint);
107 var mid,tem:longint;
108 begin
109     push(p);
110     if (tr[p].l=l)and(tr[p].r=r) then
111     begin
112         tr[p].mx:=ave;
113         tr[p].mi:=ave;
114         tr[p].wait:=true;
115         exit;
116     end;
117     mid:=(tr[p].l+tr[p].r) >> 1;
118     if r<=mid then insert(p << 1,l,r,ave) else
119         if l>mid then insert(p << 1+1,l,r,ave) else
120         begin
121             insert(p << 1,l,mid,ave);
122             insert(p << 1+1,mid+1,r,ave);
123         end;
124     tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
125     tr[p].mi:=min(tr[p << 1].mi,tr[p << 1+1].mi);
126 end;
127
128 function lca(x,y:longint):longint;
129 var tem,i:longint;
130 begin
131     if deep[x]<deep[y] then
132     begin
133         tem:=x;x:=y;y:=tem;
134     end;
135     if deep[x]<>deep[y] then
136     begin
137         i:=trunc(ln(deep[x]-deep[y])/ln(2));
138         while deep[x]>deep[y] do
139         begin
140             while deep[x]-deep[y]>=1 << i do x:=fa[x][i];
141             dec(i);
142         end;
143     end;
144     if x=y then exit(x);
145     i:=trunc(ln(n)/ln(2));
146     while fa[x][0]<>fa[y][0] do
147     begin
148         while fa[x][i]<>fa[y][i] do
149         begin
150             x:=fa[x][i];y:=fa[y][i];
151         end;
152         dec(i);
153     end;
154     exit(fa[x][0]);
155 end;
156
157 function query(p,l,r:longint):longint;
158 var mid,tem:longint;
159 begin
160     push(p);
161     if (tr[p].l=l)and(tr[p].r=r) then exit(tr[p].mx);
162     mid:=(tr[p].l+tr[p].r) >> 1;
163     if r<=mid then exit(query(p << 1,l,r)) else
164         if l>mid then exit(query(p << 1+1,l,r)) else
165         exit(max(query(p << 1,l,mid),query(p << 1+1,mid+1,r)));
166 end;
167
168 procedure dop(p,l,r:longint);
169 var mid,tem:longint;
170 begin
171     push(p);
172     if (tr[p].l=l)and(tr[p].r=r) then
173     begin
174         tem:=tr[p].mx;tr[p].mx:=-tr[p].mi;tr[p].mi:=-tem;
175         tr[p].op:=true;
176         exit;
177     end;
178     mid:=(tr[p].l+tr[p].r) >> 1;
179     if r<=mid then dop(p << 1,l,r) else
180         if l>mid then dop(p << 1+1,l,r) else
181         begin
182             dop(p << 1,l,mid);
183             dop(p << 1+1,mid+1,r);
184         end;
185     tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
186     tr[p].mi:=min(tr[p << 1].mi,tr[p << 1+1].mi);
187 end;
188
189 function solve(x,y:longint):longint;
190 var mx:longint;
191 begin
192     mx:=-maxlongint;
193     while belong[x]<>belong[y] do
194     begin
195         mx:=max(mx,query(1,pos[belong[x]],pos[x]));
196         x:=fa[belong[x]][0];
197     end;
198     if x<>y then mx:=max(mx,query(1,pos[y]+1,pos[x]));
199     exit(mx);
200 end;
201
202 procedure mend(x,y:longint);
203 begin
204     while belong[x]<>belong[y] do
205     begin
206         dop(1,pos[belong[x]],pos[x]);
207         x:=fa[belong[x]][0];
208     end;
209     if x<>y then dop(1,pos[y]+1,pos[x]);
210 end;
211
212 begin
213     readln(test);
214     for tt:=1 to test do
215     begin
216         readln;
217         readln(n);j:=0;
218         fillchar(link,sizeof(link),0);
219         fillchar(next,sizeof(next),0);
220         fillchar(deep,sizeof(deep),0);
221         fillchar(fa,sizeof(fa),0);
222         for i:=1 to n-1 do
223         begin
224             readln(x,y,z);
225             add(x,y,z);
226         end;
227         deep[1]:=1;dfs1(1);
228         cnt:=0;dfs2(1,1);
229         build(1,1,n);
230         for i:=1 to n do insert(1,pos[i],pos[i],v[i]);
231         read(ch);
232         while ch<>‘D‘ do
233         begin
234             if ch=‘Q‘ then
235             begin
236                 readln(ch,ch,ch,ch,x,y);
237                 t:=lca(x,y);
238                 writeln(max(solve(x,t),solve(y,t)));
239             end else
240             if ch=‘N‘ then
241             begin
242                 readln(ch,ch,ch,ch,ch,x,y);
243                 t:=lca(x,y);
244                 mend(x,t);mend(y,t);
245             end else
246             begin
247                 readln(ch,ch,ch,ch,ch,x,y);
248                 insert(1,pos[son[x]],pos[son[x]],y);
249             end;
250             read(ch);
251         end;
252         readln;
253     end;
254 end.
时间: 2024-08-26 03:53:05

[POJ3237]Tree解题报告|树链剖分|边剖的相关文章

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

树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设(u,v)为轻边,则size(v)<=size(u)/2 (一旦大于了那必然是重边) 也就是一条路径上每增加一条轻边节点个数就会减少一半以上,那么显然根到任意一个节点路径上的轻边条数一定不会超过log(n)(不然节点就没了啊23333) 重链定义为一条极长的连续的且全由重边构成的链. 容易看出重链两两

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

interlinkage: https://jzoj.net/senior/#main/show/3175 description: 给定一棵N 个节点的树,标号从1~N.每个点有一个权值.要求维护两种操作:1. C i x(0<=x<2^31) 表示将i 点权值变为x2. Q i j x(0<=x<2^31) 表示询问i 到j 的路径上有多少个值为x的节点 solution: 链剖 把颜色离散化,对每种颜色分别搞一颗线段树 直接搞会炸空间,因此要动态开点 感觉树上莫队好像也可以

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

Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写一个程序依次完成这m个操作. 与上一题差别不大,主要就是solve过程要根据左端点和右端点的颜色处理合并时候的情况 线段树的每个节点要记录颜色段数|最左边的颜色|最右边的颜色 同时往下传的时候标记要做好(之前那道题是单点修改所以不用考虑

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

Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的.但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数: ? Change k w:将第k条树枝上毛毛果的个数改变为w个. ? Cover u v w:将节点u与节点

HDU5052 Yaoge’s maximum profit(树链剖分)点权更新,经典题

Yaoge's maximum profit Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 662    Accepted Submission(s): 182 Problem Description Yaoge likes to eat chicken chops late at night. Yaoge has eaten to

【POJ3237】Tree(树链剖分)

题意:在一棵N个节点,有边权的树上维护以下操作: 1:单边修改,将第X条边的边权修改成Y 2:区间取反,将点X与Y在树上路径中的所有边边权取反 3:区间询问最大值,询问X到Y树上路径中边权最大值 n<=10000 CAS<=20 思路:做了2天,改出来的一刻全身都萎掉了 边权转点权,点权就是它到父亲的边的边权,加一些反向标记 取反的标记TAG下传时不能直接赋值为-1,而是将原先的标记取反 多组数据时倍增数组,深度也需要清零 树链剖分不能取第一条边,需要+1 1 const oo=2000000

【POJ3237】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 throughN − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions

【POJ3237】Tree 树链剖分

题意: change,把第i条边权值改成v negate,把a到b路径上所有权值取相反数(*(-1)) query,询问a到b路径上所有权值的最大值 树链剖分. 以前一直不会,但是我恶补LCT了,所以先学一下. 对于现在的水平来说,树剖太水了,自己翻资料吧,我只提供一个还算不错的代码. 扒代码的时候可以用我的这个. 附rand和pai. 代码: #include <cstdio> #include <cstring> #include <iostream> #inclu

hdu 4912 Paths on the tree(树链剖分+贪心)

题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道,要求尽量选出多的通道,并且两两通道不想交. 解题思路:用树链剖分求LCA,然后根据通道两端节点的LCA深度排序,从深度最大优先选,判断两个节点均没被标 记即为可选通道.每次选完通道,将该通道LCA以下点全部标记. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include