説明
毎日搾乳のために、ファーマージョンの 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)、牛の範囲を表す に B インクルーシブ。
行2 .. N +1:ライン I +1は、牛の高さは、単一の整数が含ま I
線 N 2 ... N + Q +1:二つの整数 A と B (1≤ A ≤ B ≤ N)、牛の範囲を表す に B インクルーシブ。
出力
行1 .. Q:各行は、応答に対応し、範囲内の最も高いと最短牛の高さの差を表す単一の整数を含んでいます。
サンプル入力
6 3
1
7
3
4
2
5
1〜5
4 6
2 2
サンプル出力
6 3つの。 0
アイデア:タイトル最大値と最小値との間の所与のクエリ間隔の差を意味する、STは、典型的なアルゴリズム、最もRMQ間隔の問い合わせの値です。
前処理アルゴリズムST(NlogN)時間Oの列のN個の長さを考慮すると、O(1)最も値の指定された範囲を問い合わせます。
1の#include <iostreamの>
2の#include <cstdioを>
3の#include <CStringの>
4の#include <cmath>
5の#include <アルゴリズム>
6の#include <地図>
7の#include < 設定 >
8の#include <ベクトル>
9# <キュー>含む
10の#include <リスト>
11 // の#include <unordered_map>
12の#include <積層>
13 使用 名前空間STDを、
14 の#defineっ長い長い
15 のconst int型 MOD = 1E9 + 7 。
const int型 INF = 1E9 + 7 ;
17
18である CONST INT MAXN = 1E5 + 。5 ;
19
20である INT NUM [MAXN];
21は
22である INT f_max [MAXN] [ 30 ];
23である INT f_min [MAXN] [ 30 ];
24
25 int型N-、 OP、
26は
27 // [I] [j]は、サブ間隔[I、I + 2 ^ jの数の最良値を表しセットF -1] 添字は列の数です。
28 //は、番号の先頭から最大値2 ^ I jのです。
29 // 再帰境界は[0] NUM [I] =はっきりF [I]で
30 // サブ間隔[I、i]のレーンの列、すなわち最大数
31である
32 ボイドST_prework()
33 {
34 のための(int型 i = 1 ; iが<= N; iが++ )
35 {
36 f_max [I] [ 0 ] = NUM [I]。
37 f_min [I] [ 0 ] = NUM [I]。
38 }
39 INT T = LOG2(N)+ 1 。
40 のために(INT J = 1 ; J <T、J ++ )
41 {
42 のための(int型 I = 1 ; I <= N(1 << J)+ 1; I ++は)
43である { // 我々は、セクション長が倍増ハンドル再帰場合
44である f_max [I] [J] = MAX(f_max [I]、[J- 1 Iは、(+ []、f_max 。1 <<( J- 1))] [J- 1 ]);
45 f_min [I] [J] =分(f_min [I]、[J- 1 ]、f_min [I +(1 <<(J- 1))] [J - 1。]);
46 // 2の最も値の部分区間の長さ、すなわち、最もサブインターバル^ jの値が多かれ少なかれの長さ2 ^(J-1)の両半分である
47 }
48 }
49
50 }
51は、
52である // 、任意の区間[左、右]最も値を尋ねられたとき、我々は最初のkの値を計算する
53 //^ 2 <左右+を満たすK = 2 ^ 1 <(k個の+。1)
54は // の前提の下で間隔kの最大長さよりも2以下のK乗こと、すなわち
55 // 次いで、「左2から始まります^ k個"及び"数は2 ^ kが右に「終了
56 // これら二つは全区間カバーしなければならない
57である
58 INT(ST_query INT、左int型右)
59 {
60 INT K = IOG2(右+左1 )
61は、 リターン 最大[((右[左] f_max [K]、f_max 。1 << K +)。1 ] [K]) -分(f_min [左] [K]、f_min [(右1。 K <<)+ 。1 ] [K]);
62である }
63である
64
65 INTmain()の
66 {
67の // IOS :: sync_with_stdio(偽); cin.tie(0); cout.tie(0)。
68
69 のscanf(" %D%dの"、&N、&OP)。
70
71 のために(int型 i = 1 ; iがn = <I ++は)
72 のscanf(" %dを"&NUM [I])。
73
74 ST_prework()。
75
76 INTは、右から左。
77
78 のために(int型 i = 0 ; iはOP <; iは++ )
79 {
80 のscanf(" %D%dの"、及び左、および右)。
81
82 のprintf(" %d個の\ n " 、ST_query(左、右))。
83 }
84
85 戻り 0 ;
86 }