{
这个是我在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 |
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
多叉树前序后序遍历(递归)
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
多叉树前序后序遍历(非递归)
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
二叉树三序遍历 (递归)
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 .
二叉树三序遍历(非递归)
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
随机生成树
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 .
随机生成二叉树(非递归)
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原创 转载请注明出处
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.