【POJ3237】Tree(树链剖分)

题意:在一棵N个节点,有边权的树上维护以下操作:

1:单边修改,将第X条边的边权修改成Y

2:区间取反,将点X与Y在树上路径中的所有边边权取反

3:区间询问最大值,询问X到Y树上路径中边权最大值

n<=10000 CAS<=20

思路:做了2天,改出来的一刻全身都萎掉了

边权转点权,点权就是它到父亲的边的边权,加一些反向标记

取反的标记TAG下传时不能直接赋值为-1,而是将原先的标记取反

多组数据时倍增数组,深度也需要清零

树链剖分不能取第一条边,需要+1

  1 const oo=2000000000;
  2 var t:array[1..100000]of record
  3                           min,max,tag:longint;
  4                          end;
  5     f:array[0..30000,0..15]of longint;
  6     head,vet,next,dep,tid,id,flag,
  7     len,son,size,top,a,b,c,d,g,h:array[1..30000]of longint;
  8     n,m,i,tot,x,y,k,v,cas,time,z,s,tmp,fuhao:longint;
  9     ch:string;
 10
 11 function min(x,y:longint):longint;
 12 begin
 13  if x<y then exit(x);
 14  exit(y);
 15 end;
 16
 17 function max(x,y:longint):longint;
 18 begin
 19  if x>y then exit(x);
 20  exit(y);
 21 end;
 22
 23 procedure add(a,b,c:longint);
 24 begin
 25  inc(tot);
 26  next[tot]:=head[a];
 27  vet[tot]:=b;
 28  len[tot]:=c;
 29  head[a]:=tot;
 30 end;
 31
 32 procedure dfs(u:longint);
 33 var e,v,i,t:longint;
 34 begin
 35  for i:=1 to 15 do
 36  begin
 37   if dep[u]<(1<<i) then break;
 38   f[u,i]:=f[f[u,i-1],i-1];
 39  end;
 40  e:=head[u]; flag[u]:=1; size[u]:=1; son[u]:=0; t:=0;
 41  while e<>0 do
 42  begin
 43   v:=vet[e];
 44   if flag[v]=0 then
 45   begin
 46    dep[v]:=dep[u]+1;
 47    f[v,0]:=u;
 48    dfs(v);
 49    size[u]:=size[u]+size[v];
 50    if size[v]>t then
 51    begin
 52     t:=size[v]; son[u]:=v;
 53    end;
 54   end;
 55   e:=next[e];
 56  end;
 57 end;
 58
 59 procedure swap(var x,y:longint);
 60 var t:longint;
 61 begin
 62  t:=x; x:=y; y:=t;
 63 end;
 64
 65 function lca(x,y:longint):longint;
 66 var i,d:longint;
 67 begin
 68  if dep[x]<dep[y] then swap(x,y);
 69  d:=dep[x]-dep[y];
 70  for i:=0 to 15 do
 71   if d and (1<<i)>0 then x:=f[x,i];
 72  for i:=15 downto 0 do
 73   if f[x,i]<>f[y,i] then
 74   begin
 75    x:=f[x,i]; y:=f[y,i];
 76   end;
 77  if x=y then exit(x);
 78  exit(f[x,0]);
 79 end;
 80
 81 procedure pushdown(l,r,p:longint);
 82 var mid,tmp,t1,t2:longint;
 83 begin
 84  tmp:=t[p].tag;
 85  if (l=r)or(tmp=0) then exit;
 86  t[p].tag:=0;
 87  t1:=t[p<<1].min; t2:=t[p<<1].max;
 88  t[p<<1].max:=-t1; t[p<<1].min:=-t2;
 89  t1:=t[p<<1+1].min; t2:=t[p<<1+1].max;
 90  t[p<<1+1].max:=-t1; t[p<<1+1].min:=-t2;
 91  t[p<<1].tag:=-1-t[p<<1].tag; t[p<<1+1].tag:=-1-t[p<<1+1].tag;
 92
 93 end;
 94
 95 procedure pushup(p:longint);
 96 begin
 97  t[p].min:=min(t[p<<1].min,t[p<<1+1].min);
 98  t[p].max:=max(t[p<<1].max,t[p<<1+1].max);
 99 end;
100
101 procedure change(l,r,x,v,p:longint);
102 var mid:longint;
103 begin
104  pushdown(l,r,p);
105  if (l=x)and(r=x) then
106  begin
107   t[p].min:=v; t[p].max:=v;
108  // t[p].tag:=v;
109   exit;
110  end;
111  mid:=(l+r)>>1;
112  if x<=mid then change(l,mid,x,v,p<<1)
113   else change(mid+1,r,x,v,p<<1+1);
114  pushup(p);
115 end;
116
117 procedure dfs2(u,ance:longint);
118 var e,v:longint;
119 begin
120  flag[u]:=1; inc(time); tid[u]:=time; id[time]:=u; top[u]:=ance;
121  if son[u]>0 then dfs2(son[u],ance);
122  e:=head[u];
123  while e<>0 do
124  begin
125   v:=vet[e];
126   if flag[v]=0 then dfs2(v,v);
127   e:=next[e];
128  end;
129 end;
130
131 procedure build(l,r,p:longint);
132 var mid:longint;
133 begin
134  if l=r then
135  begin
136   if h[id[l]]>oo then
137   begin
138    t[p].min:=oo; t[p].max:=-oo;
139   end
140    else begin t[p].min:=h[id[l]]; t[p].max:=h[id[l]]; end;
141   t[p].tag:=0;
142   exit;
143  end;
144  mid:=(l+r)>>1;
145  build(l,mid,p<<1);
146  build(mid+1,r,p<<1+1);
147  pushup(p);
148 end;
149
150 function query(l,r,x,y,p:longint):longint;
151 var mid,t1,t2:longint;
152 begin
153  pushdown(l,r,p);
154  if (l>=x)and(r<=y) then exit(t[p].max);
155  mid:=(l+r)>>1; query:=-oo;
156  if x<=mid then query:=max(query,query(l,mid,x,y,p<<1));
157  if y>mid then query:=max(query,query(mid+1,r,x,y,p<<1+1));
158  pushup(p);
159 end;
160
161 procedure negate(l,r,x,y,p:longint);
162 var mid,t1,t2:longint;
163 begin
164  pushdown(l,r,p);
165  if (l>=x)and(r<=y) then
166  begin
167   t1:=t[p].min; t2:=t[p].max;
168   t[p].min:=-t2; t[p].max:=-t1;
169   t[p].tag:=-1;
170   exit;
171  end;
172  mid:=(l+r)>>1;
173  if x<=mid then negate(l,mid,x,y,p<<1);
174  if y>mid then negate(mid+1,r,x,y,p<<1+1);
175  pushup(p);
176 end;
177
178 procedure ngt(x,y:longint);
179 var q:longint;
180 begin
181  q:=lca(x,y);
182  while top[x]<>top[q] do
183  begin
184   negate(1,n,tid[top[x]],tid[x],1);
185   x:=f[top[x],0];
186  end;
187  if tid[q]+1<=tid[x] then negate(1,n,tid[q]+1,tid[x],1);
188  while top[y]<>top[q] do
189  begin
190   negate(1,n,tid[top[y]],tid[y],1);
191   y:=f[top[y],0];
192  end;
193  if tid[q]+1<=tid[y] then negate(1,n,tid[q]+1,tid[y],1);
194 end;
195
196 function ask(x,y:longint):longint;
197 var q:longint;
198 begin
199  q:=lca(x,y);
200  ask:=-oo;
201  while top[x]<>top[q] do
202  begin
203   ask:=max(ask,query(1,n,tid[top[x]],tid[x],1));
204   x:=f[top[x],0];
205  end;
206  if tid[q]+1<=tid[x] then ask:=max(ask,query(1,n,tid[q]+1,tid[x],1));
207  while top[y]<>top[q] do
208  begin
209   ask:=max(ask,query(1,n,tid[top[y]],tid[y],1));
210   y:=f[top[y],0];
211  end;
212  if tid[q]+1<=tid[y] then ask:=max(ask,query(1,n,tid[q]+1,tid[y],1));
213 end;
214
215 begin
216  assign(input,‘tree.in‘); reset(input);
217  assign(output,‘poj3237.out‘); rewrite(output);
218  readln(cas);
219  for v:=1 to cas do
220  begin
221   readln(n);
222   fillchar(head,sizeof(head),0); tot:=0; time:=0;
223   fillchar(flag,sizeof(flag),0);
224   fillchar(d,sizeof(d),0); fillchar(g,sizeof(g),0);
225   fillchar(h,sizeof(h),$7f); fillchar(dep,sizeof(dep),0);
226   fillchar(f,sizeof(f),0); fillchar(tid,sizeof(tid),0);
227   fillchar(id,sizeof(id),0);
228   for i:=1 to n<<2 do
229   begin
230    t[i].min:=oo; t[i].max:=-oo; t[i].tag:=0;
231   end;
232   for i:=1 to n-1 do
233   begin
234    readln(a[i],b[i],c[i]);
235    add(a[i],b[i],c[i]);
236    add(b[i],a[i],c[i]);
237   end;
238
239   dfs(1);
240   fillchar(flag,sizeof(flag),0);
241   dfs2(1,1);
242   for i:=1 to n-1 do
243   begin
244    if dep[a[i]]<dep[b[i]] then tmp:=b[i]
245     else tmp:=a[i];
246    d[i]:=tmp; g[tmp]:=i; h[tmp]:=c[i];
247   end;
248  // h[1]:=0; d[n]:=1; g[1]:=n;
249   build(1,n,1);
250   while true do
251   begin
252    readln(ch); x:=0; y:=0; k:=length(ch);
253    if ch[1]=‘D‘ then break; s:=0; fuhao:=1;
254    for i:=1 to k do
255    begin
256     if ch[i]=‘ ‘ then begin inc(s); continue; end;
257     if (s=1)and(ch[i]<>‘ ‘) then x:=x*10+ord(ch[i])-ord(‘0‘);
258     if (s=2)and(ch[i]<>‘ ‘) then
259     begin
260      if ch[i]=‘-‘ then begin fuhao:=-1; continue; end
261       else y:=y*10+ord(ch[i])-ord(‘0‘);
262     end;
263    end;
264    if ch[1]=‘C‘ then change(1,n,tid[d[x]],fuhao*y,1);
265    if ch[1]=‘N‘ then ngt(x,y);
266    if ch[1]=‘Q‘ then
267    begin
268     writeln(ask(x,y));
269     //writeln;
270    end;
271   end;
272  end;
273  close(input);
274  close(output);
275 end.
时间: 2024-10-25 05:43:37

【POJ3237】Tree(树链剖分)的相关文章

SPOJ375 Query on a tree 树链剖分

SPOJ375  Query on a tree   树链剖分 no tags You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of

SPOJ - QTREE 375 Query on a tree 树链剖分+线段树

操作1:修改第k条边权. 操作2:询问两点间最大边权. 树链剖分,然后线段树维护最大值 #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #inclu

【POJ3237】Tree 树链剖分

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

Aizu 2450 Do use segment tree 树链剖分+线段树

Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show.php?pid=39566 Description Given a tree with n (1 ≤ n ≤ 200,000) nodes and a list of q (1 ≤ q ≤ 100,000) queries, process the queries in order and out

spoj 375 Query on a tree (树链剖分)

Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of the i-th edge to ti or Q

SPOJ Query on a tree 树链剖分 水题

You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of the i-th edge to tior QUERY a b : ask fo

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

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

poj 3237 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

spoj Query on a tree(树链剖分模板题)

375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of

【BZOJ-4353】Play with tree 树链剖分

4353: Play with tree Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 31  Solved: 19[Submit][Status][Discuss] Description 给你一棵包含N个节点的树,设每条边一开始的边权为0,现在有两种操作: 1)给出参数U,V,C,表示把U与V之间的路径上的边权变成C(保证C≥0) 2)给出参数U,V,C,表示把U与V之间的路径上的边权加上C.但是如果U至V之间路径某条边的边权加上C小于0,那