合計制限時間:5000ms
単一のテストポイントの制限時間:2000ms
メモリ制限:65536kB
説明
毎日搾乳のために、ファーマージョンの Nの 牛(1≤ N ≤50,000)は、常に同じ順序で並べます。ある日、ファーマージョンは、何頭かの牛と一緒にアルティメットフリスビーのゲームを企画することにしました。物事を単純にするために、彼は搾乳ラインナップから連続した範囲の牛を連れてゲームをプレイします。ただし、すべての牛が楽しむためには、身長の違いが大きすぎないようにする必要があります。
ファーマージョンはリストにした Q (1≤ Q ≤20万)乳牛の潜在的なグループとその高さ(1つの≤ 高さ ≤1,000,000)。各グループについて、彼はあなたの助けを借りて、グループ内で最も短い牛と最も高い牛の身長の違いを判断することを望んでいます。
入る
1行目:二スペースで区切られた整数、 N および Q。
行2 .. N +1:ライン I +1は、牛の高さである単一の整数含ま I
線 N +2を.. N + Q +1:二つの整数 A と B (1≤ A ≤ B ≤ N)、A から B までの牛の範囲を表し ます。
出力
1行目。Q:各行には、応答への応答であり、範囲内で最も高い牛と最も短い牛の身長の差を示す単一の整数が含まれています。
サンプル入力
6 3 1 7 3 4 2 5 1 5 4 6 2 2
サンプル出力
6 3 0
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 50005;
const int INF = 0x7fffffff;
int N, Q;
struct node {
int L, R;
int maxv, minv;
};
node tree[4*MAXN];
void build_tree(int root, int L, int R)
{
tree[root].L = L;
tree[root].R = R;
tree[root].maxv = -INF;
tree[root].minv = INF;
if (L == R)
return;
int mid = (L+R)/2;
build_tree(root*2+1, L, mid);
build_tree(root*2+2, mid+1, R);
}
void insert(int root, int i, int v)
{
node& rt = tree[root];
rt.maxv = max(rt.maxv, v);
rt.minv = min(rt.minv, v);
if (rt.L == rt.R)
return ;
int mid = (rt.L + rt.R) / 2;
if (i <= mid)
insert(2*root+1, i, v);
else
insert(2*root+2, i, v);
}
/*
* set maxV and minV before calling this function!!!
*/
int maxV, minV;
void query(int root, int L, int R)
{
node& rt = tree[root];
if (L == rt.L && R == rt.R) {
maxV = max(maxV, rt.maxv);
minV = min(minV, rt.minv);
return;
}
int mid = (rt.L + rt.R) / 2;
if (R <= mid)
query(root*2+1, L, R);
else if (L >= mid + 1)
query(root*2+2, L, R);
else {
query(root*2+1, L, mid);
query(root*2+2, mid+1, R);
}
}
int main()
{
scanf("%d%d", &N, &Q);
build_tree(0, 0, N-1);
for (int i = 0; i < N; ++i) {
int t;
scanf("%d", &t);
insert(0, i, t);
}
for (int i = 0; i < Q; ++i) {
int l, r;
scanf("%d%d", &l, &r);
minV = INF;
maxV = -INF;
query(0, l-1, r-1);
printf("%d\n", maxV - minV);
}
return 0;
}