1 条题解

  • 0
    @ 2025-11-5 15:24:31
    • 分别计算数组中的每一个数 aia_i,能够作为某个子数组的最小值的次数
    • 也就是:找到 aia_i 左边第一个 ai\le a_i 的数的下标 lil_i
    • 找到 aia_i 右边第一个 >ai> a_i 的数的下标 rir_i
    • 那么 [li+1,,ri1][l_i + 1, \cdots, r_i - 1] 之间的数组成的子数组,其最小值都是 aia_i
    #include <bits/stdc++.h>
    using namespace std;
    
    using i64 = long long;
    const int P = 998244353;
    
    int gao(const vector<int>& a) {
        int n = a.size();
    
        // L(i): 左边第一个 <= a[i] 的数的下标 
        vector<int> L(n, -1);
    
        // R(i): 右边第一个 < a[i] 的数的下标
        vector<int> R(n, n);
    
        vector<int> s(n);  // 用来从左往右放入 a[i]
        int e = 0;  // s 中元素的个数
    
        for (int i = 0; i < n; i++) {
            // 在 s 里从后往前找到第一个 <= a[i]
            // 拿出的时候确定右边第一个 < a[s[e - 1]] 的就是 a[i]
            while (e > 0 && a[s[e - 1]] > a[i]) R[s[--e]] = i;
    
            // 放入的时候确定左边第一个 <= a[i] 的
            if (e != 0) L[i] = s[e - 1];
            s[e++] = i;
        }
    
        i64 ans = 0;
        for (int i = 0; i < n; i++) {
            ans = (ans + (i64) (i - L[i]) * (R[i] - i) * a[i]) % P;
        }
        return ans;
    }
    
    int main() {	
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
    
        int n;
        cin >> n;
        vector<int> a(n);
        for (int i = 0; i < n; i++) cin >> a[i];
        cout << gao(a) << '\n';
    
        return 0;
    }
    
    
    • 1

    信息

    ID
    162
    时间
    100ms
    内存
    32MiB
    难度
    5
    标签
    递交数
    76
    已通过
    28
    上传者