bzoj1036 [ZJOI2008]树的统计Count

Description

  一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

   输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 
     对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

  对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input

4

1 2

2 3

4 1

4 2 1 3

12

QMAX 3 4

QMAX 3 3

QMAX 3 2

QMAX 2 3

QSUM 3 4

QSUM 2 1

CHANGE 1 5

QMAX 3 4

CHANGE 3 6

QMAX 3 4

QMAX 2 4

QSUM 3 4

Sample Output

4

1

2

2

10

6

5

6

5

16

树链剖分裸题,然而写的时候发现自己忘了线段树的单点修改只会区间修改

  1 program rrr(input,output);
  2 type
  3   tree=record
  4      l,r,sum,max:longint;
  5   end;
  6   pointer=^nodetype;
  7   nodetype=record
  8      t:longint;
  9      next:pointer;
 10   end;
 11 var
 12   a:array[0..4*30030]of tree;
 13   b:array[0..30030]of pointer;
 14   p:pointer;
 15   q,dep,belong,head,idx,father,siz,num:array[0..30030]of longint;
 16   v:array[0..30030]of boolean;
 17   n,m,i,j,x,y,h,t,cnt,tot,ans:longint;
 18   s:string;
 19 function max(a,b:longint):longint;
 20 begin
 21    if a>b then exit(a) else exit(b);
 22 end;
 23 procedure add(x,y:longint);
 24 begin
 25    new(p);p^.t:=y;p^.next:=b[x];b[x]:=p;
 26 end;
 27 procedure bfs;
 28 begin
 29    fillchar(v,sizeof(v),false);
 30    h:=0;t:=1;q[1]:=1;dep[1]:=0;v[1]:=true;
 31    while h<t do
 32       begin
 33          inc(h);p:=b[q[h]];
 34          while p<>nil do
 35             begin
 36                if not v[p^.t] then
 37                   begin
 38                      inc(t);q[t]:=p^.t;v[p^.t]:=true;
 39                      dep[p^.t]:=dep[q[h]]+1;father[p^.t]:=q[h];
 40                   end;
 41                p:=p^.next;
 42             end;
 43       end;
 44    for i:=1 to n do siz[i]:=1;
 45    for i:=n downto 2 do inc(siz[father[q[i]]],siz[q[i]]);
 46 end;
 47 procedure dfs(k:longint);
 48 var
 49   p:pointer;
 50   i,max:longint;
 51 begin
 52    if siz[k]=1 then exit;
 53    p:=b[k];max:=0;
 54    while p<>nil do begin if p^.t<>father[k] then if siz[p^.t]>max then begin max:=siz[p^.t];i:=p^.t; end;p:=p^.next; end;
 55    belong[i]:=belong[k];inc(cnt);idx[i]:=cnt;
 56    dfs(i);
 57    if siz[k]=2 then exit;
 58    p:=b[k];
 59    while p<>nil do
 60       begin
 61          if (p^.t<>father[k]) and (p^.t<>i) then
 62             begin
 63                inc(cnt);idx[p^.t]:=cnt;
 64                inc(tot);head[tot]:=p^.t;belong[p^.t]:=tot;
 65                dfs(p^.t);
 66             end;
 67          p:=p^.next;
 68       end;
 69 end;
 70 procedure build(k,l,r:longint);
 71 var
 72   mid,i:longint;
 73 begin
 74    a[k].l:=l;a[k].r:=r;
 75    if l=r then begin a[k].sum:=num[l];a[k].max:=num[l];exit; end;
 76    mid:=(l+r)>>1;i:=k<<1;
 77    build(i,l,mid);build(i+1,mid+1,r);
 78    a[k].max:=max(a[i].max,a[i+1].max);a[k].sum:=a[i].sum+a[i+1].sum;
 79 end;
 80 procedure work;
 81 begin
 82    j:=pos(‘ ‘,s);
 83    val(copy(s,1,j-1),x);
 84    delete(s,1,j);val(s,y);
 85 end;
 86 procedure change(k:longint);
 87 var
 88   mid,i:longint;
 89 begin
 90    if a[k].l=a[k].r then begin a[k].max:=y;a[k].sum:=y;exit; end;
 91    mid:=(a[k].l+a[k].r)>>1;i:=k<<1;
 92    if x<=mid then change(i) else change(i+1);
 93    a[k].sum:=a[i].sum+a[i+1].sum;a[k].max:=max(a[i].max,a[i+1].max);
 94 end;
 95 function askmax(k,x,y:longint):longint;
 96 var
 97   mid,i:longint;
 98 begin
 99    if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].max);
100    mid:=(a[k].l+a[k].r)>>1;i:=k<<1;
101    askmax:=-30000;
102    if x<=mid then askmax:=askmax(i,x,y);
103    if mid<y then askmax:=max(askmax,askmax(i+1,x,y));
104 end;
105 function asksum(k,x,y:longint):longint;
106 var
107   mid,i:longint;
108 begin
109    if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].sum);
110    mid:=(a[k].l+a[k].r)>>1;i:=k<<1;
111    asksum:=0;
112    if x<=mid then asksum:=asksum(i,x,y);
113    if mid<y then asksum:=asksum+asksum(i+1,x,y);
114 end;
115 function ask1:longint;
116 begin
117    ans:=-30000;
118    while belong[x]<>belong[y] do
119       if dep[head[belong[x]]]>dep[head[belong[y]]] then begin ans:=max(ans,askmax(1,idx[head[belong[x]]],idx[x]));x:=father[head[belong[x]]]; end
120       else begin ans:=max(ans,askmax(1,idx[head[belong[y]]],idx[y]));y:=father[head[belong[y]]]; end;
121    if dep[x]>dep[y] then exit(max(ans,askmax(1,idx[y],idx[x])))
122    else exit(max(ans,askmax(1,idx[x],idx[y])));
123 end;
124 function ask2:longint;
125 begin
126    ans:=0;
127    while belong[x]<>belong[y] do
128       if dep[head[belong[x]]]>dep[head[belong[y]]] then begin ans:=ans+asksum(1,idx[head[belong[x]]],idx[x]);x:=father[head[belong[x]]]; end
129       else begin ans:=ans+asksum(1,idx[head[belong[y]]],idx[y]);y:=father[head[belong[y]]]; end;
130    if dep[x]>dep[y] then exit(ans+asksum(1,idx[y],idx[x]))
131    else exit(ans+asksum(1,idx[x],idx[y]));
132 end;
133 begin
134    assign(input,‘r.in‘);assign(output,‘r.out‘);reset(input);rewrite(output);
135    readln(n);
136    for i:=1 to n do b[i]:=nil;
137    for i:=1 to n-1 do begin readln(x,y);add(x,y);add(y,x); end;
138    bfs;
139    belong[1]:=1;head[1]:=1;tot:=1;cnt:=1;idx[1]:=1;
140    dfs(1);
141    for i:=1 to n do read(num[idx[i]]);
142    build(1,1,n);
143    readln(m);
144    for i:=1 to m do
145       begin
146          readln(s);
147          if s[2]=‘M‘ then begin delete(s,1,5);work;writeln(ask1); end;
148          if s[2]=‘S‘ then begin delete(s,1,5);work;writeln(ask2); end;
149          if s[2]=‘H‘ then begin delete(s,1,7);work;x:=idx[x];change(1); end;
150       end;
151    close(input);close(output);
152 end.
时间: 2024-08-10 00:07:19

bzoj1036 [ZJOI2008]树的统计Count的相关文章

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

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

bzoj1036: [ZJOI2008]树的统计Count(树链剖分+线段树维护)

bzoj1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MB Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的

BZOJ1036: [ZJOI2008]树的统计Count - 树链剖分 -

1036: [ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 Input 输入的第一行为一个整数n,表示节点的个数.接下来n – 1

bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题

[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 Input 输入的第一行为一个整数n,表示节点的个数.接下来n – 1行,每行

[BZOJ1036/ZJOI2008]树的统计(Count)-树链剖分

Problem 树的统计 题目大意 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 So Lazy No Solution 裸的树链剖分,题解一搜一大把.就连这个都炸了几次.我太菜了... AC

bzoj1036 [ZJOI2008]树的统计Count(树链剖分)

Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 Input 输入的第一行为一个整数n,表示节点的个数.接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条

[BZOJ1036] [ZJOI2008] 树的统计Count (LCT)

Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 Input 输入的第一行为一个整数n,表示节点的个数.接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条

【块状树】【树链剖分】bzoj1036 [ZJOI2008]树的统计Count

很早之前用树链剖分写过,但是代码太长太难写,省选现场就写错了. 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 #define lson rt<<1,l,m 6 #define rson rt<<1|1,m+1,r 7 #define maxn 60000 8 int n,m,u,v; 9 int V[maxn],Next[

BZOJ1036[ZJOI2008]树的统计Count 题解

题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.有一些操作:1.把结点u的权值改为t:2.询问从点u到点v的路径上的节点的最大权值 3.询问从点u到点v的路径上的节点的权值和. 思路: 进行轻重树链剖分,再根据每个节点的dfs序建立线段树,维护其最大值以及和,询问时用树剖后的结果将重链作为区间一段一段求和. 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #de