洛谷 P1816 忠誠 題解

P1816 忠誠

題目描述

老管家是一個聰明能幹的人。他爲財主工做了整整10年,財主爲了讓自已帳目更加清楚。要求管家天天記k次帳,因爲管家聰明能幹,於是管家老是讓財主十分滿意。可是因爲一些人的唆使,財主仍是對管家產生了懷疑。因而他決定用一種特別的方法來判斷管家的忠誠,他把每次的帳目按1,2,3…編號,而後不定時的問管家問題,問題是這樣的:在a到b號帳中最少的一筆是多少?爲了讓管家沒時間做假他老是一次問多個問題。ios

輸入格式

輸入中第一行有兩個數m,n表示有m(m<=100000)筆帳,n表示有n個問題,n<=100000。spa

第二行爲m個數,分別是帳目的錢數code

後面n行分別是n個問題,每行有2個數字說明開始結束的帳目編號。get

輸出格式

輸出文件中爲每一個問題的答案。具體查看樣例。io

輸入輸出樣例

輸入 #1class

10 3
1 2 3 4 5 6 7 8 9 10
2 7
3 9
1 10stream

輸出 #1方法

2 3 1數據

【思路】

ST表 + 倍增 + RMQ區間最值查詢

【題目大意】

求區間最小值

【題目分析】

區間最小值
看到這裏必定會不由自主想到能夠用ST表來作這種區間最值得題目

【核心思路】

讀入數據
而後預處理出ST表裏面對應的區間最值是多少
最後輸入須要查詢的區間
而後輸出區間最小值就行了

【注意】

作這種區間最值題目的時候
必定要考慮好區間的範圍
不要到時候求a到b區間範圍內數最值
由於處理不當致使求到了a到b範圍外面
就會出現很大的問題

【完整代碼】

#include<iostream>
#include<cstdio>

using namespace std;

int read()
{
    int sum = 0,fg = 1;
    char c = getchar();
    while(c < '0' || c > '9')
    {
        if(c == '-')fg = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
    {
        sum = sum * 10 + c - '0';
        c = getchar();
    }
    return sum * fg;
}
const int Max = 100005;
int f[Max][22];
int LG[Max]; 

int main()
{
    int m = read(),n = read();
    for(register int i = 1;i <= m;++ i)
        f[i][0] = read();
    for(register int j = 1;(1 << j) <= m;++ j)
        for(register int i = 1;i + (1 << j) - 1 <= m;++ i)
            f[i][j] = min(f[i][j - 1],f[i + (1 << (j - 1))][j - 1]);
    for(register int i = 1;(1 << i) <= m;++ i)
        LG[(1 << i)] = i;
    for(register int i = 1;i <= m;++ i)
        if(LG[i] == 0)
            LG[i] = LG[i - 1];
    for(register int i = 1;i <= n;++ i)
    {
        int a = read(),b = read();
        int k = LG[b - a + 1];
        cout << min(f[a][k],f[b - (1 << k) + 1][k]) << " ";
    }
    return 0;
}
相關文章
相關標籤/搜索