Description
Little Ming很喜歡訓練自己的快速讀能力,他最近找到一種新的考驗并訓練快速讀能力的方法,在一行具有很多數的數列里任意指定某一段長度,從左往右掃視一遍后說出這段數列中的最大值,但他不想一直只使用一個數列,所以他請了他的好朋友,一位非常喜歡編程的學生,Little Little來幫忙在原數列上時不時的做一些修改,給他出題并檢驗他的答案是否正確。Little Little在做修改操作時會選取某個點修改它的值,在做出題操作時給出某一段的左右端點。
Input
本題目包含多組測試,請處理到文件結束。
在每個測試的第一行,有兩個正整數 N 和 M ( 0<N<=200000,0<M<5000 )
第二行包含N個整數,代表初始時數列中的數據。
接下來有M行。每一行有一個字符 C (只取'Q'或'S') ,和兩個正整數A,B。
當C為'Q'的時候,表示這是一條出題操作,A,B為端點下標值,有可能A比B大。
當C為'S'的時候,表示這是一條修改操作,要求把第A個數修改為B。
Output
對于每一次出題操作,在一行里面輸出最大的數。
相鄰2組測試之間要有一個空行。
Sample Input
5 6
1 2 3 4 5
Q 1 5
S 3 6
Q 3 4
Q 4 5
S 2 9
Q 1 5
Sample Output
5
6
5
9
這是一道再基礎不過的線段樹題了,不多贅述,相見代碼及注釋。可先參閱:http://www.shnenglu.com/hoolee/archive/2012/07/29/185531.html
細節:題目中說A可能大于B,要注意交換A、B。
1
#include<stdio.h>
2
#include<stdlib.h>
3
#include<string.h>
4
#define LEN 2000000
5
int N, M;
6
typedef struct MyNode
7

{
8
int bg, ed;
9
int max;
10
int lf, rt;
11
}MyNode;
12
MyNode A[LEN];//動態分配空間很耗時,先用數組A[]申請足夠大的空間。
13
int count = 0;//記錄A[]數組的使用情況,指向最后一個使用節點
14
int num[LEN];
15
int max(int a, int b)
16

{
17
if(a > b)
18
return a;
19
return b;
20
}
21
void makeTree(int t)
22

{
23
/**//*
24
* t指向A[]節點的位置。
25
* 建樹過程為: 1.先有根節點,2.再建左右子樹,3.然后修改根節點的子樹指針
26
*/
27
if(A[t].bg == A[t].ed)
28
{
29
A[t].max = num[A[t].bg];
30
//A[t].lf = A[t].rt = 1;
31
return;
32
}
33
int mid = (A[t].bg + A[t].ed) / 2;
34
int lf = ++count;//開辟空間
35
int rt = ++count;
36
A[lf].bg = A[t].bg;
37
A[lf].ed = mid;
38
A[rt].bg = mid + 1;
39
A[rt].ed = A[t].ed;
40
makeTree(lf);
41
makeTree(rt);
42
A[t].lf = lf;
43
A[t].rt = rt;
44
A[t].max = max(A[lf].max, A[rt].max);
45
}
46
int query(int t, int bg, int ed)
47

{
48
/**//*
49
給定區間[bg, ed],查詢區間的最大值,
50
[bg, ed]區間與t節點代表的區間有四種關系:(令(A[t].bg + A[t].ed) / 2)
51
1.他倆是同一個區間,查詢成功,返回A[t].max
52
2.bg <= mid, 接著查詢t的左子樹
53
3.ed > min,接著查詢t的右子樹
54
4.否認則,同時查詢t的左右子樹
55
*/
56
if(A[t].bg == bg && A[t].ed == ed)
57
{
58
return A[t].max;
59
}
60
int mid = (A[t].bg + A[t].ed) / 2;
61
if(ed <= mid)
62
{
63
return query(A[t].lf, bg, ed);
64
}
65
else if(bg > mid)
66
{
67
return query(A[t].rt, bg, ed);
68
}
69
else
70
{
71
return max(query(A[t].lf, bg, mid), query(A[t].rt, mid + 1, ed));
72
}
73
74
}
75
void change(int ap, int p, int b)
76

{
77
/**//*
78
ap指向當前節點,p是要修改的位置,b為值
79
分為3中情況:
80
1.A[ap]為葉子節點,修改A[ap].max為b
81
2.p在ap的左子樹上,去左子樹上查詢
82
3.p在ap的右子樹上,去右子樹上查詢
83
*/
84
if(A[ap].bg == A[ap].ed)
85
{
86
A[ap].max = b;
87
return;
88
}
89
int mid = (A[ap].bg + A[ap].ed) / 2;
90
if(p <= mid)
91
{
92
change(A[ap].lf, p, b);
93
}
94
else// p > mid
95
{
96
change(A[ap].rt, p, b);
97
}
98
A[ap].max = max(A[A[ap].lf].max, A[A[ap].rt].max);//子樹的max改變了,也要修改父節點的max值
99
}
100
int main()
101

{
102
int i, j;
103
int spaceline = 0;
104
while(scanf("%d%d", &N, &M) == 2)
105
{
106
if(spaceline)
107
{
108
putchar(10);
109
}
110
else
{
111
spaceline = 1;
112
}
113
114
for(int i = 0; i < N; i++)
115
scanf("%d", &num[i]);
116
count = 0;
117
int t = ++count;
118
A[t].bg = 0;
119
A[t].ed = N - 1;
120
makeTree(t);
121
for(int i = 0; i < M; i++)
122
{
123
getchar();
124
char c = getchar();
125
int a, b;
126
scanf("%d%d", &a, &b);
127
if(c == 'Q')
128
{
129
if(a > b)
130
{
131
int t2 = a;
132
a = b;
133
b = t2;
134
}
135
int rs = query(1, a - 1, b - 1);
136
printf("%d\n", rs);
137
}
138
else
139
{
140
change(1, a - 1, b);
141
}
142
//printf("c=%c a=%d b=%d\n", c, a, b);
143
}
144
}
145
146
//system("pause");
147
return 0;
148
}
149
其實這道題我先是用java寫的,TLE,同樣的思想,用C++寫,410MS AC。下面是超時的java代碼,可能是new太耗時了。

TLE的java代碼
1
import java.util.*;
2
import java.util.Scanner;
3
4
class Main
{
5
6
static ArrayList<Integer> numary = new ArrayList<Integer>();
7
8
public static void main(String[] args)
{
9
////
10
//System.out.println("hello!");
11
//
12
Scanner sc = new Scanner(System.in);
13
boolean spaceline = false;
14
while(sc.hasNext())
{
15
int N = sc.nextInt();
16
int M = sc.nextInt();
17
numary.clear();
18
for(int i = 0; i < N; i++)
{//read number
19
int t = sc.nextInt();
20
numary.add(t);
21
}
22
MyNode tree = new MyNode(0, N - 1, 0);
23
makeTree(tree);
24
25
sc.nextLine();
26
if(spaceline)
{
27
System.out.println();
28
}
29
else
30
spaceline = true;
31
for(int i = 0; i < M; i++)
{
32
String instr = sc.nextLine();
33
String[] strs = instr.split(" ");
34
if(strs[0].equals("Q"))
{//query
35
int a = Integer.parseInt(strs[1]);
36
int b = Integer.parseInt(strs[2]);
37
if(a > b)
{
38
int t2 = a;
39
a = b;
40
b = t2;
41
}
42
int rs = query(tree, a - 1, b - 1);
43
System.out.println(rs);
44
}
45
else
{//change
46
int p = Integer.parseInt(strs[1]);
47
int v = Integer.parseInt(strs[2]);
48
change(tree, p - 1, v);
49
}
50
}
51
}//while sc.hasNext()
52
53
}
54
static void change(MyNode nd, int p, int v)
{
55
if(nd.bg == nd.ed)
{
56
57
nd.max = v;
58
return;
59
}
60
int mid = (nd.bg + nd.ed) / 2;
61
62
if(p <= mid)
{
63
change(nd.lf, p, v);
64
}
65
else
{
66
change(nd.rt, p, v);
67
68
}
69
nd.max = max(nd.lf.max, nd.rt.max);
70
}
71
72
static int query(MyNode nd, int bg, int ed)
{
73
if(nd.bg == bg && nd.ed == ed)
74
return nd.max;
75
int mid = (nd.bg + nd.ed) / 2;
76
if(ed <= mid)
{
77
return query(nd.lf, bg, ed);
78
}
79
else if(bg > mid)
{
80
return query(nd.rt, bg, ed);
81
}
82
else
{
83
return max(query(nd.lf, bg, mid), query(nd.rt, mid + 1, ed));
84
}
85
}
86
87
static int max(int a, int b)
{
88
if(a > b)
89
return a;
90
return b;
91
}
92
93
static void makeTree(MyNode nd)
{
94
if(nd.bg == nd.ed)
{
95
nd.max = numary.get(nd.bg);
96
return;
97
}
98
int mid = (nd.bg + nd.ed) / 2;
99
MyNode lf = new MyNode(nd.bg, mid, 0);
100
MyNode rt = new MyNode(mid + 1, nd.ed, 0);
101
102
makeTree(lf);
103
makeTree(rt);
104
nd.lf = lf;
105
nd.rt = rt;
106
nd.max = max(lf.max, rt.max);
107
108
}
109
}
110
class MyNode
{
111
int bg;
112
int ed;
113
int max = Integer.MIN_VALUE;
114
MyNode lf;
115
MyNode rt;
116
MyNode(int bg, int ed, int max)
{
117
this.bg = bg;
118
this.ed = ed;
119
this.max = max;
120
}
121
}
posted on 2013-04-28 18:47
小鼠標 閱讀(254)
評論(0) 編輯 收藏 引用 所屬分類:
數據結構