TIOJ-2017

B.廢文大資料 mining

https://tioj.ck.tp.edu.tw/problems/2017

Description

給定一個序列 $a_i$ ,問有多少區間 $[l,r]$ 使得存在一個 $m \leq r$ 滿足 $\sum\limits _ {i=l}^m a_i < 0$?

Solution

先對 $a_i$ 做前綴 $s_k = \sum\limits _ {i=1}^k a_i$
對於一個固定的 $l$ 來說,題目等價於找到一個最小的 $m$ 使得 $s_m - s _ {l-1} < 0$
在 $m$ 之後的 $r$ 都會被算在答案裡面

可以用單調隊列幫每個 $i$ 找到最小的 $i’$ 使得 $s _ {i’} < s_i$ ,複雜度 $\mathcal{O}(n)$

AC code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <bits/stdc++.h>
using namespace std;
const int N = 1000025;
long long n,a[N],stk[N],p,R[N];
signed main() {
    ios_base::sync_with_stdio(0), cin.tie(0);
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) a[i] += a[i-1];
    //for(int i = 0; i <= n; i++) cout << v[i] << ' '; cout << '\n';
    long long sum = 0;
    for(int i = n; i >= 0; i--) {
        while(p && a[stk[p-1]] >= a[i]) --p;
        R[i] = (p ? stk[p-1]-1 : n) - i;
        stk[p++] = i;
    }
    for(int i = 0; i < n; i++) sum += R[i];
    cout << n*(n+1)/2 - sum << '\n';
}
comments powered by Disqus