考虑枚举 $r$,计算出所有满足题意的 $l$ 的数量。 设 $S$ 为 $A$ 的前缀和数组,若 $L \le S_r - S_l \le R$,则区间 $(l,r]$ 满足题意。 作一个简单的变化就能求出 $S_l$ 的范围:$S_r - R\le S_l\le S_r - L$。 那么我们依次枚举 $1\ldots N$ 作为 $r$,维护 $S_0 \ldots S_{r - 1}$ 即可。 可以使用树状数组+离散化或者动态开点权值线段树,我选择的是树状数组+离散化。 时间复杂度 $O(N\log N)$。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1e5 + 5; typedef long long ll; const int maxm = 4e5 + 5; int n,cnt; ll L,R,a[maxn],d[maxm],c[maxm],s[maxn]; int sum[maxm]; int lowbit(int x) { return x & -x; } void add(int x,int y) { if(!x)return ; for(;x <= cnt;x += lowbit(x))sum[x] += y; return ; } int query(int x) { int ans = 0; for(;x;x -= lowbit(x))ans += sum[x]; return ans; } int main() { scanf("%d%lld%lld",&n,&L,&R); d[++ cnt] = s[0] = 0; for(int i = 1;i <= n;++ i) { scanf("%lld",&a[i]); s[i] = s[i - 1] + a[i]; d[++ cnt] = s[i]; d[++ cnt] = s[i] - L; d[++ cnt] = s[i] - R; } for(int i = 1;i <= cnt;++ i)c[i] = d[i]; sort(c + 1 , c + 1 + cnt); cnt = unique(c + 1 , c + 1 + cnt) - c - 1; for(int i = 1;i <= 3 * n + 1;++ i)d[i] = lower_bound(c + 1 , c + 1 + cnt , d[i]) - c; add(d[1] , 1);//提前插入 s[0] ll ans = 0; for(int i = 1;i <= n;++ i) { ans += query((int)d[3 * i]) - query((int)d[3 * i + 1] - 1); add((int)d[3 * i - 1] , 1); } printf("%lld",ans); return 0; }
题目3687 [BJOI2016]回转寿司
7
评论
2024-06-22 16:44:05
|