線段樹初級(區間最大數)
其實就是對樹進行二分查找 (當然需要結合遞歸)
思路:
要從區間中找到最大數,當然可以暴力求解,但你不怕超時嗎???
so 讓我們來學習線段樹吧!!!!!!!!!!!!!!!
在c++里下面這個代碼是極快的(哇咔咔!!!)
題目描述
給出一列數共N個,將其從1到N編號,進行M次查詢[X, Y](X<=Y),給出第X個數到第Y個數間最大的數。
輸入
一組測試數據,第一行輸入N,M(1<=N, M<=10^5),第二行N個數;之后M行,每行分別為X,Y。給出一列數共N個,將其從1到N編號,進行M次查詢[X, Y](X<=Y),給出第X個數到第Y個數間最大的數。
輸出
對於每個[X, Y]輸出編號在X和Y之間(包括X,Y)的最大值。每行輸出一個結果。
樣例輸入
5 2
4 3 1 2 5
1 4
2 5
樣例輸出
4
5
#include <iostream>
#include <cstdio>
#include <cstring>
using
namespace
std;
#define maxn 100010
struct
N
{
int
l, r, max;
} tree[maxn * 4];
//注意乘三
int
num[maxn];
void
build(
int
node,
int
l,
int
r)
{
tree[node].l = l;
tree[node].r = r;
if
(l == r)
{
scanf
(
"%d"
, &tree[node].max);
return
;
}
int
mid = (l + r) / 2;
build(node * 2, l, mid);
build(node * 2 + 1, mid + 1, r);
tree[node].max = max(tree[node << 1].max, tree[node << 1 | 1].max);
return
;
}
int
query(
int
node,
int
ql,
int
qr)
{
int
l = tree[node].l;
int
r = tree[node].r;
if
(l == ql && r == qr)
return
tree[node].max;
//if (l == r) return tree[node].max;
int
mid = (l + r) / 2;
if
(qr <= mid)
return
query(node << 1, ql, qr);
else
if
(ql > mid)
return
query(node << 1 | 1, ql, qr);
else
return
max(query(node << 1, ql, mid), query(node << 1 | 1, mid + 1, qr));
}
int
main()
{
int
n, m;
int
ql, qr;
scanf
(
"%d %d"
, &n, &m);
build(1, 1, n);
for
(
int
i = 0; i < m; i++)
{
scanf
(
"%d %d"
, &ql, &qr);
printf
(
"%d\n"
, query(1, ql, qr));
}
}
用2*n和2*n+1不會出現遺漏和重復的樹編號,這樣就可以完美的遞歸啦!!!!!!!!!!!!!1