洛谷題單指南-線性表-P2234 [HNOI2002] 營業額統計

江城伍月發表於2024-03-13

原題連結:https://www.luogu.com.cn/problem/P2234

題意解讀:要計算每一天最小波動值的和,需要對每一天求最小波動值,再求和,如果暴力法,時間複雜度在1+2+3+......+32767≈5*10^8,可能會超時。

解題思路:

1、暴力法:由於本題測試資料比較水,實測暴力求解直接可以AC,由於沒有技術含量,不做具體介紹。

2、set法:

對於每一個數x,只需要找前面出現的跟x最接近的數

那麼,很容易想到,對出現的每一個數,維護一個有序的資料結構,當把x插入之前,找到x的前後數(剛好>=x的、剛好<x的),看差的絕對值哪個小即可

要維護有序的資料結構,set比較合適,另外set還提供了lower_bound(x)函式,可以在logN的複雜度查詢第一個>=指定值的位置

100分程式碼:

#include <bits/stdc++.h>
using namespace std;

set<int> st;
int ans;

int main()
{
    int n, x;
    cin >> n;
    for(int i = 1; i <= n; i++) 
    {
        cin >> x;
        int minx = INT_MAX;
        if(i == 1) minx = x;
        else
        {
            set<int>::iterator itr = st.lower_bound(x); //先查詢>=x的第一個數的位置
            if(itr != st.end()) minx = min(minx, abs(*itr - x)); //計算第一個可能的最小波動值
            if(itr != st.begin())
            {
                set<int>::iterator itl = itr;
                itl--; //itl是<x的最大的數的位置
                minx = min(minx, abs(*itl - x)); //計算第二個可能的最小波動值
            }
        }
        st.insert(x); //將x插入set
        ans += minx;
    }
    cout << ans;

    return 0;
}

相關文章