1. 程式人生 > >1068 : RMQ-ST算法

1068 : RMQ-ST算法

隨機數 turn 0ms 區間 意義 hihocode coder 宇宙 div

#1068 : RMQ-ST算法

時間限制:10000ms 單點時限:1000ms 內存限制:256MB

描述

小Hi和小Ho在美國旅行了相當長的一段時間之後,終於準備要回國啦!而在回國之前,他們準備去超市采購一些當地特產——比如漢堡(大霧)之類的回國。

但等到了超市之後,小Hi和小Ho發現者超市擁有的商品種類實在太多了——他們實在看不過來了!於是小Hi決定向小Ho委派一個任務:假設整個貨架上從左到右拜訪了N種商品,並且依次標號為1到N,每次小Hi都給出一段區間[L, R],小Ho要做的是選出標號在這個區間內的所有商品重量最輕的一種,並且告訴小Hi這個商品的重量,於是他們就可以毫不費勁的買上一大堆東西了——多麽可悲的選擇困難癥患者。

(雖然說每次給出的區間仍然要小Hi來進行決定——但是小Hi最終機智的選擇了使用隨機數生成這些區間!但是為什麽小Hi不直接使用隨機數生成購物清單呢?——問那麽多做什麽!)

提示一:二分法是宇宙至強之法!(真的麽?)

提示二:線段樹不也是二分法麽?

輸入

每個測試點(輸入文件)有且僅有一組測試數據。

每組測試數據的第1行為一個整數N,意義如前文所述。

每組測試數據的第2行為N個整數,分別描述每種商品的重量,其中第i個整數表示標號為i的商品的重量weight_i。

每組測試數據的第3行為一個整數Q,表示小Hi總共詢問的次數。

每組測試數據的第N+4~N+Q+3行,每行分別描述一個詢問,其中第N+i+3行為兩個整數Li, Ri,表示小Hi詢問的一個區間[Li, Ri]。

對於100%的數據,滿足N<=10^6,Q<=10^6, 1<=Li<=Ri<=N,0<weight_i<=10^4。

輸出

對於每組測試數據,對於每個小Hi的詢問,按照在輸入中出現的順序,各輸出一行,表示查詢的結果:標號在區間[Li, Ri]中的所有商品中重量最輕的商品的重量。

樣例輸入
10
7334
1556
8286
1640
2699
4807
8068
981
4120
2179
5
3 4
2 8
2 4
6 8
7 10
樣例輸出
1640
981
1556
981
981

方法一:線段樹
 1 #include <iostream>
 2
#define N 1000005 3 #define inf 0x3f3f3f3f 4 using namespace std; 5 6 int tree[N<<2]; 7 8 void pushup(int rt){ 9 tree[rt] = min(tree[rt<<1],tree[rt<<1|1]); 10 } 11 12 void build(int l,int r,int rt){ 13 if(l == r){ 14 scanf("%d",&tree[rt]); 15 // cout<<tree[rt]<<" "<<rt<<endl; 16 return ; 17 } 18 int mid = (l+r)>>1; 19 build(l,mid,rt<<1); 20 build(mid+1,r,rt<<1|1); 21 pushup(rt); 22 } 23 24 int query(int l,int r,int L ,int R,int rt){ 25 //l,r 為變換區級,L,R為給定區級 26 if(r<L||l>R){ 27 return inf; 28 } 29 if(l>=L&&r<=R){ 30 return tree[rt]; 31 } 32 int ans; 33 int mid = (l+r)>>1; 34 ans = min(query(l,mid,L,R,rt<<1),query(mid+1,r,L,R,rt<<1|1)); 35 return ans; 36 } 37 38 int n,m; 39 int main(){ 40 scanf("%d",&n); 41 build(1,n,1); 42 scanf("%d",&m); 43 while(m--){ 44 int x,y; 45 scanf("%d%d",&x,&y); 46 int cnt = query(1,n,x,y,1); 47 printf("%d\n",cnt); 48 } 49 return 0; 50 }



方法二:RMQ,st

 1 #include <iostream>
 2 #include <cmath>
 3 #define N 1000005
 4 using namespace std;
 5 int an[N];
 6 int dp[N][40];
 7 int t,n;
 8 
 9 void st(int n){
10     for(int i = 1;i <= n;++i)
11         dp[i][0] = an[i];
12     for(int i = 1;(1<<i) <= n; ++i){
13         for(int j = 1; j+(1<<i)-1 <= n; ++j){
14             dp[j][i] = min(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);
15         }
16     }
17 }
18 int rmq(int l,int r){
19     int k = 0;
20     while((1<<(k+1)) <= (r-l+1))
21         k++;
22     return min(dp[l][k],dp[r-(1<<k)+1][k]);
23 }
24 int main(){
25     scanf("%d",&t);
26     for(int i=1;i<=t;i++){
27         scanf("%d",&an[i]);
28     }
29     st(t);
30     scanf("%d",&n);
31     for(int i=1;i<=n;i++){
32         int x,y;
33         scanf("%d%d",&x,&y);
34         printf("%d\n", rmq(x,y));
35     }
36     return 0;
37 }

1068 : RMQ-ST算法