[PKU 3321] 树状数组 & 树的非递归遍历

{

这个是我在cnblogs的第一篇日志

以前的内容会慢慢补上

就先写这2天解决的问题吧

}

原题  http://acm.pku.edu.cn/JudgeOnline/problem?id=3321

题意

  用边集给定一棵n个节点的有根树

  初始节点权值一律为1

  给定q个操作{Ch,' ',k}

  Ch为

    'Q'-询问以k为根的子树的节点的权值和

    'C'-改变节点k的权值(xor 1)

数据结构

  邻接表

  树状数组

算法

  建树

    用邻接表读入边集

      有100000个点

      给定的是边集 无法确定父子关系

      (程序中用数组模拟链表 模拟数组要开两倍)

    用dfs按后序遍历重新编号

      我们对树后序遍历后可以发现

        一棵子树中除根外所有节点的出栈时间都早于根

        一棵子树中的节点应当是连续出栈的

      于是乎

        可以用一个区间来表示一棵子树啰

        根节点的出栈时间戳max就是区间右端点

        区间左端点是子树中节点进栈时间戳的最小值 有2种求法

          第一种是纪录以每个节点为根的子树中最早的进栈的节点的时间戳min

            根节点出栈的时候 在所有儿子节点的min值中取最小 求出根的min值

            叶子的min值就是出栈时间戳max

          第二种是直接纪录根的进栈时间戳x min值等于x+1

      dfs要用非递归做 不然会爆栈(100000个点)

  统计

    树状数组

      求子树权值和不就是求区间权值和了么

      再加上修改单个元素

      树状数组可以在nlog2n的和时间里完美解决这个问题

p.s.

  有人递归dfs也过了 汗

  还有 数组十万不够 狂晕

  求区间左端点第一种方法复杂度仍为O(n) 不超时

    因为这棵树的总度和为2n 所以总的扫描每个节点的儿子min值求最小是2n次

    不过常数会大点

  这个问题伪装的太好了 根本看不出是树状数组

  顺便贴一下

    树与二叉树遍历的各种程序(递归 非递归)

    随机生成生成树、二叉树的程序

我的程序

  这个问题的程序

7494797Master_Chivu3321Accepted5560K329MSPascal1386B2010-08-20 13:46:36
 
 
  
1 const maxn = 100000 ;
2   var n,i,u,v,tt,top,time,x,p,q:longint;
3 sum,c,map,tag,min,stack,h,f: array [ 1 ..maxn] of longint;
4 next,tab: array [ 1 ..maxn shl 1 ] of longint;
5 ch,blank:char;
6   function lowbit(x:longint):longint;
7   begin
8 lowbit: = x and - x;
9   end ;
10   procedure insert(x,v:longint);
11   var y:longint;
12   begin
13 y: = x;
14   while y <= n do
15 begin
16 c[y]: = c[y] + v;
17 y: = y + lowbit(y);
18 end ;
19   end ;
20   function query(x:longint):longint;
21   var y,ans:longint;
22   begin
23 ans: = 0 ;
24 y: = x;
25   while y > 0 do
26 begin
27 ans: = ans + c[y];
28 y: = y - lowbit(y);
29 end ;
30 query: = ans;
31   end ;
32   begin
33 assign(input, ' apple.in ' ); reset(input);
34 assign(output, ' apple.out ' ); rewrite(output);
35 readln(n);
36 tt: = 0 ;
37   for i: = 1 to n - 1 do
38 begin
39 readln(u,v);
40 inc(tt); tab[tt]: = v;
41 next[tt]: = map[u]; map[u]: = tt;
42 inc(tt); tab[tt]: = v;
43 next[tt]: = map[u]; map[u]: = tt;
44 end ;
45 top: = 1 ; stack[top]: = 1 ;
46 time: = 0 ;
47   while top > 0 do
48 begin
49 x: = stack[top];
50 if h[x] = 0
51 then begin
52 min[x]: = time + 1 ;
53 h[x]: = 1 ;
54 p: = map[x];
55 while p <> 0 do
56 begin
57 if f[tab[p]] = 0
58 then begin
59 f[tab[p]]: = 1 ;
60 inc(top);
61 stack[top]: = tab[p];
62 end ;
63 p: = next[p];
64 end ;
65 end
66 else begin
67 inc(time);
68 tag[x]: = time;
69 dec(top);
70 end ;
71 end ;
72   for i: = 1 to n do
73 insert(i, 1 );
74 readln(q);
75   for i: = 1 to q do
76 begin
77 read(ch); read(blank); readln(x);
78 case ch of
79 ' Q ' : writeln(query(tag[x]) - query(min[x] - 1 ));
80 ' C ' : begin
81 sum[x]: = sum[x] xor 1 ;
82 insert(tag[x],sum[x] xor 1 - sum[x]);
83 end ;
84 end ;
85 end ;
86 close(input); close(output);
87   end .
88  

 



多叉树前序后序遍历(递归)



 
  
1 const max = 1000 ;
2   var h,tab,next,map: array [ 1 ..max] of longint;
3 tt,n,u,v,i:longint;
4   procedure NLR(x:longint);
5 var j,i,p:longint;
6 temp: array [ 1 .. 100 ] of longint;
7 begin
8 if (x = 0 ) or (h[x] = 1 ) then exit;
9 h[x]: = 1 ;
10 write(x, ' ' );
11 p: = map[x]; i: = 0 ;
12 while p <> 0 do
13 begin
14 inc(i); temp[i]: = tab[p];
15 p: = next[p];
16 end ;
17 for j: = i downto 1 do
18 NLR(temp[j]);
19 end ;
20 procedure LRN(x:longint);
21 var i,j,p:longint;
22 temp: array [ 1 .. 100 ] of longint;
23 begin
24 if (x = 0 ) or (h[x] = 1 ) then exit;
25 h[x]: = 1 ;
26 p: = map[x]; i: = 0 ;
27 while p <> 0 do
28 begin
29 inc(i); temp[i]: = tab[p];
30 p: = next[p];
31 end ;
32 for j: = i downto 1 do
33 LRN(temp[j]);
34 write(x, ' ' );
35 end ;
36 begin
37 assign(input, ' trav.in ' ); reset(input);
38 assign(output, ' trav0.out ' ); rewrite(output);
39 readln(n);
40 tt: = 0 ;
41 for i: = 1 to n - 1 do
42 begin
43 readln(u,v);
44 inc(tt); tab[tt]: = v;
45 next[tt]: = map[u];
46 map[u]: = tt;
47 inc(tt); tab[tt]: = u;
48 next[tt]: = map[v];
49 map[v]: = tt;
50 end ;
51 NLR( 1 );
52 fillchar(h,sizeof(h), 0 );
53 writeln;
54 LRN( 1 );
55 close(input); close(output);
56 end .
57

 


多叉树前序后序遍历(非递归)


 



 
  
1 const maxn = 100000 ;
2 var now,tt,i,n,u,v,top,p:longint;
3 f,h: array [ 1 ..maxn] of 0 .. 1 ;
4 d,map,stack: array [ 1 ..maxn] of longint;
5 tab,next: array [ 1 ..maxn shl 1 ] of longint;
6 begin
7 assign(input, ' trav.in ' ); reset(input);
8 assign(output, ' trav.out ' ); rewrite(output);
9 readln(n);
10 tt: = 0 ;
11 for i: = 1 to n - 1 do
12 begin
13 readln(u,v);
14 inc(tt); tab[tt]: = v;
15 next[tt]: = map[u];
16 map[u]: = tt;
17 inc(tt); tab[tt]: = u;
18 next[tt]: = map[v];
19 map[v]: = tt;
20 inc(d[u]); inc(d[v]);
21 end ;
22 { for i:=1 to n do
23 begin
24 p:=map[i];
25 while p<>0 do
26 begin
27 write(tab[p],' ');
28 p:=next[p];
29 end;
30 writeln;
31 end; }
32 // NL - R
33 fillchar(h,sizeof(h), 0 );
34 top: = 1 ; stack[top]: = 1 ;
35 h[ 1 ]: = 1 ;
36 while top > 0 do
37 begin
38 write(stack[top], ' ' );
39 p: = map[stack[top]];
40 dec(top);
41 while p <> 0 do
42 begin
43 if h[tab[p]] = 0
44 then begin
45 inc(top);
46 stack[top]: = tab[p];
47 h[tab[p]]: = 1 ;
48 end ;
49 p: = next[p];
50 end ;
51 end ;
52 writeln;
53 // L - RN
54 fillchar(h,sizeof(h), 0 );
55 fillchar(stack,sizeof(stack), 0 );
56 top: = 1 ; stack[top]: = 1 ;
57 f[ 1 ]: = 1 ;
58 while top > 0 do
59 begin
60 now: = stack[top];
61 if d[now] = 1
62 then begin
63 write(now, ' ' );
64 dec(top);
65 end
66 else if h[now] = 0
67 then begin
68 h[now]: = 1 ;
69 p: = map[now];
70 while p <> 0 do
71 begin
72 if f[tab[p]] = 0
73 then begin
74 f[tab[p]]: = 1 ;
75 inc(top);
76 stack[top]: = tab[p];
77 end ;
78 p: = next[p];
79 end ;
80 end
81 else begin
82 write(now, ' ' );
83 dec(top);
84 end ;
85 end ;
86 close(input); close(output);
87 end .
88

 



二叉树三序遍历 (递归)


 
  
1 // Recursion
2 const maxn = 1000 ;
3 var n,i,x,root:longint;
4 l,r: array [ 1 ..maxn] of longint;
5 procedure NLR( var x:longint);
6 begin
7 if x = 0 then exit;
8 write(x, ' ' );
9 NLR(l[x]);
10 NLR(r[x]);
11 end ;
12 procedure LNR( var x:longint);
13 begin
14 if x = 0 then exit;
15 LNR(l[x]);
16 write(x, ' ' );
17 LNR(r[x]);
18 end ;
19 procedure LRN( var x:longint);
20 begin
21 if x = 0 then exit;
22 LRN(l[x]);
23 LRN(r[x]);
24 write(x, ' ' );
25 end ;
26 begin
27 assign(input, ' binary.in ' ); reset(input);
28 assign(output, ' binary0.out ' ); rewrite(output);
29 readln(n);
30 for i: = 1 to n do
31 begin
32 read(x);
33 readln(l[x],r[x]);
34 end ;
35 root: = 1 ;
36 NLR(root);
37 writeln;
38 LNR(root);
39 writeln;
40 LRN(root);
41 writeln;
42 close(input); close(output);
43 end .

 



二叉树三序遍历(非递归)

 
  
1 // NO Recursion
2 const maxn = 1000000 ;
3 var n,i,x,top:longint;
4 h,l,r,stack: array [ 1 ..maxn] of longint;
5 begin
6 assign(input, ' binary.in ' ); reset(input);
7 assign(output, ' binary.out ' ); rewrite(output);
8 readln(n);
9 for i: = 1 to n do
10 begin
11 read(x);
12 readln(l[x],r[x]);
13 end ;
14 top: = 1 ; stack[ 1 ]: = 1 ;
15 while top > 0 do
16 begin
17 x: = stack[top];
18 write(x, ' ' );
19 dec(top);
20 if r[x] <> 0
21 then begin
22 inc(top);
23 stack[top]: = r[x];
24 end ;
25 if l[x] <> 0
26 then begin
27 inc(top);
28 stack[top]: = l[x];
29 end ;
30 end ;
31 writeln;
32 top: = 1 ; stack[ 1 ]: = 1 ;
33 fillchar(h,sizeof(h), 0 );
34 while top > 0 do
35 begin
36 x: = stack[top];
37 if (l[x] <> 0 ) and (h[l[x]] = 0 )
38 then begin
39 inc(top);
40 stack[top]: = l[x];
41 h[l[x]]: = 1 ;
42 end
43 else begin
44 write(x, ' ' );
45 dec(top);
46 if (r[x] <> 0 ) and (h[r[x]] = 0 )
47 then begin
48 inc(top);
49 stack[top]: = r[x];
50 h[r[x]]: = 1 ;
51 end ;
52 end ;
53 end ;
54 writeln;
55 top: = 1 ; stack[ 1 ]: = 1 ;
56 fillchar(h,sizeof(h), 0 );
57 while top > 0 do
58 begin
59 x: = stack[top];
60 if (l[x] <> 0 ) and (h[l[x]] = 0 )
61 then begin
62 inc(top);
63 stack[top]: = l[x];
64 h[l[x]]: = 1 ;
65 end
66 else if (r[x] <> 0 ) and (h[r[x]] = 0 )
67 then begin
68 inc(top);
69 stack[top]: = r[x];
70 h[r[x]]: = 1 ;
71 end
72 else begin
73 write(x, ' ' );
74 dec(top);
75 end ;
76 end ;
77 writeln;
78 close(input); close(output);
79 end .
80

 



随机生成树



 
  
1 // Bob ' s Random Spanning Tree Builder V1.01
2 const maxn = 1000000 ;
3 var n,i,x,y:longint;
4 f,h: array [ 1 ..maxn] of longint;
5 s:string;
6 begin
7 randomize;
8 assign(input, ' input.txt ' ); reset(input);
9 readln(n);
10 readln(s);
11 assign(output,s); rewrite(output);
12 writeln(n);
13 i: = 0 ;
14 f[ 1 ]: = 1 ; h[ 1 ]: = 1 ;
15 while i < n - 1 do
16 begin
17 inc(i);
18 x: = random(n) + 1 ;
19 while h[x] = 1 do
20 x: = random(n) + 1 ;
21 h[x]: = 1 ;
22 y: = random(i - 1 ) + 1 ;
23 writeln(f[y], ' ' ,x);
24 f[i + 1 ]: = x;
25 end ;
26 close(input); close(output);
27 end .

 



随机生成二叉树(非递归)

 
  
1 // Bob ' s Random Binary Tree V1.11
2 const maxn = 1000000 ;
3 var l,r: array [ 1 ..maxn] of longint;
4 stack: array [ 1 ..maxn] of record x,s:longint; end ;
5 top,n,tt,nx,ns,y,i:longint;
6 s:string;
7 begin
8 randomize;
9 assign(input, ' input.txt ' ); reset(input);
10 readln(n);
11 readln(s);
12 assign(output,s); rewrite(output);
13 tt: = 1 ; top: = 1 ;
14 stack[ 1 ].x: = 1 ; stack[ 1 ].s: = n;
15 while top > 0 do
16 begin
17 nx: = stack[top].x;
18 ns: = stack[top].s;
19 dec(top);
20 y: = random(ns);
21 if y > 0 then begin
22 inc(tt); l[nx]: = tt;
23 inc(top); stack[top].x: = tt; stack[top].s: = y;
24 end ;
25 if ns - 1 - y > 0 then begin
26 inc(tt); r[nx]: = tt;
27 inc(top); stack[top].x: = tt; stack[top].s: = ns - 1 - y;
28 end ;
29 if tt >= n then break;
30 end ;
31 writeln(tt);
32 for i: = 1 to tt do
33 writeln(i, ' ' ,l[i], ' ' ,r[i]);
34 close(input); close(output);
35 end .
36

 



感觉这个问题没练树状数组 练了写非递归

BOB HAN原创 转载请注明出处

//Bob's Random Binary Tree Builder V1.00
const    maxn=1000;
var    n,root,tt,i:longint;
    l,r:array[1..maxn]of longint;
procedure build(var x:longint; s:longint);
var    y:longint;
begin
if s<1 then exit;
inc(tt); x:=tt;
y:=random(s);
build(l[x],y);
build(r[x],s-1-y);
end;
begin
randomize;
assign(input,'input.txt'); reset(input);
assign(output,'binary.in'); rewrite(output);
readln(n);
root:=0;
tt:=0;
build(root,n);
writeln(tt);
for i:=1 to tt do
    writeln(i,' ',l[i],' ',r[i]);
close(input); close(output);
end.
//Bob's Random Binary Tree Builder V1.00
const maxn=1000;
var n,root,tt,i:longint;
l,r:array[1..maxn]of longint;
procedure build(var x:longint; s:longint);
var y:longint;
begin
if s<1 then exit;
inc(tt); x:=tt;
y:=random(s);
build(l[x],y);
build(r[x],s-1-y);
end;
begin
randomize;
assign(input,'input.txt'); reset(input);
assign(output,'binary.in'); rewrite(output);
readln(n);
root:=0;
tt:=0;
build(root,n);
writeln(tt);
for i:=1 to tt do
writeln(i,' ',l[i],' ',r[i]);
close(input); close(output);
end.

转载于:https://www.cnblogs.com/Booble/archive/2010/08/20/1804579.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值