CF1042D Petya and Array(cdq分治/資料結構)
阿新 • • 發佈:2021-07-25
題面
有一個長度為 \(n\) 的序列 \(a\) 和一個數 \(t\),求有多少個區間 \([l,r]\) 滿足 \(a_{l}+a_{l+1}+...+a_{r}<t\)。\((n\le 2×10^5,|t|\le 2×10^{14},|a_i|\le 10^9)\)
題解
將題目轉化為“求有多少對 \(l,r\) 滿足 \(S_r-S_l<t\)",其中 \(S\) 為字首和,\(l\in [0,n-1],r\in [1,n]\)。
法1:CDQ分治
當分治到 \([l,r]\) 時
- 遞迴求解 \([l,mid]\) 與 \([mid+1,r]\)。
- 此時 \([l,mid]\) 與 \([mid+1,r]\)
- 將區間 \([l,r]\) 排序。
#include<bits/stdc++.h> #define int long long const int maxn = 2e5 + 5; int n, t, a[maxn], S[maxn]; int ans = 0; void solve(int l, int r) { if(l == r) return ; int mid = (l + r) >> 1; solve(l, mid); solve(mid + 1, r); int L = l, R = mid + 1; while(L <= mid && R <= r) { if(S[L] + t <= S[R]) { ++L; } else { ans += mid - L + 1; ++R; } } std::sort(S + l, S + r + 1); } signed main() { std::ios::sync_with_stdio(0); std::cin.tie(0), std::cout.tie(0); std::cin >> n >> t; for(int i = 1; i <= n; ++i) { std::cin >> a[i]; S[i] = S[i - 1] + a[i]; } solve(0, n); std::cout << ans; return 0; }