当前位置: 首页 > news >正文

CF1042D Petya and Array 题解

题目描述

给定一个长度为 n 的数组 a(元素可正可负可为0),求有多少个非空连续子段 [l, r]\ 满足子段和 $$a_l + a_{l+1} + \dots + a_r < t$$

输入格式

第一行两个整数 n 和 \(t\)\(1 \le n \le 200\,000\)\(|t| \le 2 \times 10^{14}\)
第二行 (n) 个整数 \(a_i\)(\(|a_i| \le 10^9\)

输出格式

输出满足条件的子段个数

解题思路

前缀和转化

设前缀和数组 \(pre[i] = \sum_{k=1}^{i} a_k\),特别地 \(pre[0] = 0\)
区间 \([l, r]\) 的和可表示为 \(pre[r] - pre[l-1]\)
条件 $$pre[r] - pre[l-1] < t$$ 等价于

\[pre[l-1] > pre[r] - t. \]

固定右端点 \(r\),我们需要统计有多少个左端点 \(l\)\((1 \le l \le r\))满足上式,即有多少个下标 \(j = l-1\)\(0 \le j \le r-1\))使得 \(pre[j] > pre[r] - t\)

因此,我们可以从左到右扫描数组,维护一个数据结构,其中已经插入了 \(pre[0], pre[1], \dots, pre[r-1]\)。对于当前 (r),查询数据结构中值大于 (pre[r] - t) 的元素个数,累加到答案,然后将 (pre[r]) 插入数据结构

数据结构选择

需要支持动态插入和查询“大于某值的元素个数”

  • 平衡树(如 std::multiset)配合 upper_bound 可求大于某值的个数,但需要手写距离(可用 distance,但复杂度可能退化)
  • 更优雅的方式:使用基于红黑树的 __gnu_pbds::tree,它提供了 order_of_key 方法,返回严格小于给定键的元素个数
    我们只需插入所有前缀和(由于可能有重复值,用 pair<ll, ll> 存储,第二维为下标保证唯一性),然后对于给定的 need = pre[r] - t

    \[\text{大于 need 的个数} = \text{总个数} - \text{order_of_key}(\{need, INF\}). \]

    其中 {need, INF} 是一个大于所有值为 need 的元素的键,这样 order_of_key 返回的就是小于等于 need 的元素个数

算法步骤

  1. 读入 (n, t) 和数组 (a)
  2. 计算前缀和 (pre[i])
  3. 初始化一个 ordered_set,类型为 tree<pair<ll, ll>, ...>,插入 {pre[0], 0}
  4. 遍历 (i = 1 \dots n):
    • 计算 need = pre[i] - t
    • 查询 cnt = st.order_of_key({need, LLONG_MAX}),表示小于等于 need 的元素个数
    • 当前答案加上 st.size() - cnt,即为大于 need 的元素个数
    • 插入 {pre[i], i}
  5. 输出答案

复杂度分析

  • 时间复杂度:每个前缀和插入一次、查询一次,每次操作 \(O(\log n)\),总复杂度 \(O(n \log n)\)
  • 空间复杂度:\(O(n)\)

代码实现(C++)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using ll = long long;
using namespace __gnu_pbds;
using ordered_set = tree<pair<ll, ll>, null_type, less<pair<ll, ll>>, rb_tree_tag, tree_order_statistics_node_update>;
const ll N = 2e5 + 10, mod = 998244353, inf = LLONG_MAX;
ll n, w, m, t, a[N];
void solve() {cin >> n >> t;ll ans = 0;vector<ll> pre(n + 2, 0);for (int i = 1; i <= n; i++) {cin >> a[i];pre[i] = pre[i - 1] + a[i];}ordered_set st;st.insert({pre[0],0});//放入下表为0的值for (int i = 1; i <= n; i++) {ll need=pre[i]-t;ll nn=st.order_of_key({need,inf});ans += st.size()-nn;//大于need的个数st.insert({pre[i],i});}cout << ans << '\n';
}
int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int _ = 1;// cin >> _;while (_--) {solve();}return 0;
}
http://www.jsqmd.com/news/424977/

相关文章:

  • 工业机器视觉之测量软件(WPF+Halcon+海康相机)
  • 寒假作业(2月9号)
  • 寒假作业(2月10号)
  • 寒假作业(2月3号)
  • 卷积神经网络的引入5 —— 当空间结构被彻底打乱时,CNN 还能成立吗?
  • 寒假作业(2月4号)
  • AI渗透测试工具:从脚本跑腿到Agent大脑的范式革命
  • 游戏服务端架构:消息流水线模型(有序而高效) - 码客
  • 行业内有实力的2026板材十大品牌 - 品牌推荐(官方)
  • HTTPServlet
  • 【翻译】MAUI 的.NET 11预览版:使用内联C#表达式简化XAML
  • 别再盲目喂Prompt了!2026年大模型分水岭:深挖“向量引擎”如何让Claude-Opus-4.6实现逻辑进化!
  • solidworks 多实体 工程图 带多平板视图 无代码
  • 高中语文提分秘籍!揭秘五大宝藏线上培训机构 - 品牌测评鉴赏家
  • 实测5家热门初中文言文线上机构!不吹不黑,避坑指南+精准推荐 - 品牌测评鉴赏家
  • 2026中考语文拉分王!5家文言文提分网校揭秘 - 品牌测评鉴赏家
  • PMP-项目管理:软件开发都有哪些开发方式 / 迭代开发 / 增量开发 / 瀑布开发 / 敏捷开发 / 螺旋开发
  • 互联网大厂Java面试:从Spring Boot到微服务架构探讨
  • PMP-项目管理:什么情况下会修改项目章程 / 什么情况下会通知发起人 / 什么情况下会通知项目管理委员会 / 什么情况下会通知变更委员会
  • 2026年管型母线制造企业推荐,大截面输电更稳定 - 品牌鉴赏师
  • 2026年 Trae 收费模式改变 —— AI 编程“免费午餐”终结后的生存法则
  • 京东e卡回收平台哪家口碑最好?3招选对 - 京顺回收
  • 论文写不动?一键生成论文工具,千笔ai写作 VS 灵感ai,MBA专属
  • 揭秘!高中语文线上提分秘籍,这些机构凭什么脱颖而出 - 品牌测评鉴赏家
  • 终于再见
  • 初中语文写作逆袭指南:揭秘高口碑线上机构 - 品牌测评鉴赏家
  • PyTorch神经网络组件之MaxPool2d
  • LeetCode 1680.连接连续二进制数字:O(n)左移位运算
  • 避雷!2026初中语文写作线上机构实测,这两家真能帮孩子提分 - 品牌测评鉴赏家
  • 2026年02月总结及随笔之欢欢喜喜过大年