[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次

    不过常数会大点

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

  顺便贴一下

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

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

我的程序

  这个问题的程序

7494797 Master_Chivu 3321 Accepted 5560K 329MS Pascal 1386B 2010-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.

posted on 2010-08-20 14:49  Master_Chivu  阅读(1231)  评论(1编辑  收藏  举报

导航