DMOJ

news/2024/9/29 23:34:57

B. Infinity Card Decks

题目描述

\(N\) 张牌,第 \(i\) 张牌打出需要 \(A_i\) 能量,获得 \(B_i\) 能量。一开始你有 \(M\) 的能量。

如果一些牌,无论怎么无限的按照随机顺序打出,都不会缺少能量,则我们称这是一个无限牌组

求有多少个子区间是无限牌组。

思路

很容易想到,一个无限牌组必须满足以下条件。

  1. \(\sum A_i \le \sum B_i\),因为如果不满足该条件,那么每经过一轮能量就会减少,所以最终一定会不够。
  2. 在第一轮打出时不可能缺少能量。因为满足条件 1,所以能量每过一轮都是单调不降的,所以第一轮的能量是最少的。

我们先来看条件 2:

  • 我们要枚举一张牌 \(i\),使得在出这张牌的时候能量不足。在这之前,肯定会把其他 \(A_j>B_j且i\ne j\)\(j\) 出掉。
    • 如果 \(A_i\le B_i\),那么此时要满足 \(M\ge A_i+\sum \max(0,A_j-B_j)\)
    • 否则如果 \(A_i>B_i\),那么此时要满足 \(M\ge A_i+(\sum \max(0,A_j-B_j)-(A_i-B_j))=B_i+\sum \max(0,A_j-B_j)\)
  • 上面两式合起来就是 \(M\ge \min (A_i,B_i)+\sum \max(0,A_j-B_j)\)

所以一个区间 \([l,r]\) 要满足 \(M\ge \max\limits_{i=l}^r\{\min (A_i,B_i)\}+\sum \limits_{i=l}^r \max(0,A_i-B_i)\)。这个使用双指针求解。

接着我们考虑满足条件 1,我们可以做一个 \(A_i-B_i\) 的前缀和,离散化后用树状数组统计数量即可。

空间复杂度 \(O(N)\),时间复杂度 \(O(N\log N)\)

代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;const int MAXN = 1000005;int n, m, a[MAXN], b[MAXN], log_2[MAXN];
ll ans, st[21][MAXN], pre[MAXN], tr[MAXN];
vector<ll> X;int Getmax(int l, int r) {return max(st[log_2[r - l + 1]][l], st[log_2[r - l + 1]][r - (1 << log_2[r - l + 1]) + 1]);
}int lowbit(int x) {return x & -x;
}void update(int p, ll x) {for(; p <= n + 1; tr[p] += x, p += lowbit(p)) {}
}ll Getsum(int p) {ll sum = 0;for(; p; sum += tr[p], p -= lowbit(p)) {}return sum;
}int main() {ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);cin >> n >> m;for(int i = 1; i <= n; ++i) {cin >> a[i];}for(int i = 1; i <= n; ++i) {cin >> b[i];pre[i] = pre[i - 1] + a[i] - b[i];X.emplace_back(pre[i]);st[0][i] = min(a[i], b[i]);}X.emplace_back(0);sort(X.begin(), X.end()), X.erase(unique(X.begin(), X.end()), X.end());for(int i = 0; i <= n; ++i) {pre[i] = lower_bound(X.begin(), X.end(), pre[i]) - X.begin() + 1;}for(int i = 1; i <= 20; ++i) {for(int j = 1; j <= n; ++j) {if(j + (1 << i) - 1 <= n) {st[i][j] = max(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);}}}for(int i = 2; i <= n; ++i) {log_2[i] = log_2[i / 2] + 1;}ll sum = 0;for(int i = 1, j = 1; i <= n; sum -= max(0, a[i] - b[i]), update(pre[i], -1), ++i) {for(; j <= n && Getmax(i, j) + sum + max(0, a[j] - b[j]) <= m; sum += max(0, a[j] - b[j]), update(pre[j], 1), ++j) {}ans += Getsum(pre[i - 1]);if(j == i) {sum += max(0, a[j] - b[j]), update(pre[j], 1), ++j;}}cout << ans;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/66362.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

9.23课堂作业

我所选择的主题是安全教育。在校园内外,我们经常听到的、看到的一些不安全事故频繁发生。尽管在校园内,也会有无端横祸向我们飞来,血的教训让我们懂得,校园安全与师生密切相关,关系到学生能否健康成长,完成学业。关系到老师能否在个宁静安全的环境中教书育人。校园安全是…

streamlit

示例代码import streamlit as st import pandas as pd from pathlib import Path@st.cache_data def load_data_from_csv(file_path):return pd.read_csv(file_path)if __name__ == __main__:file_path = Path(__file__).parent.parent / resources / data.csvdata = load_data…

PlantSimulation的socket交互之TCP

PlantSimulation的socket交互之TCP1.python的socket TCP客户端建立 其实可以任选python或plantsimulation作为客户端,博主因研究需要,将python设为客户端。plant设为服务器。1 """2 Created on Sat December 14 21:00:00 20213 @author: Zhang Litong- Nanjin…

2024-2025-1 20241419《计算机基础与程序设计》第一周学习总结

课程 要求 目标:基于VirtualBox虚拟机安装Ubuntu 作业正文:基于VirtualBox虚拟机安装Ubuntu 教材学习内容总结 1.计算系统:由软件、硬件及其管理的数据组成的用于解决问题以及与其所处环境进行交互的一种动态实体。 2.计算系统的分层:计算系统的各个具体组成部分。 3.抽象:…

Rhino基础操作3 - 出图篇

Rhino建模后出一系列的图的操作:建模后做倒角、利用快照切换视图。 出图有:纯线稿、截面图、剖面图、模型的说明书类、模型渲染图。注:非结构建模专业,纯粹是用Rhino写实用新型专利,所以学了下Rhino的建模。不理解最简面、曲线阶数的影响等,请原谅。--本篇导航--圆角(假…

vscode中文乱码问题

vscode中文乱码解决方法 简单粗暴:文件——>首选项——>设置——>搜索设置——>encoding——>Files:Encoding ——> gbk 修改实现注:可在同文件夹下实现效果; 如果不是固定常用,方法二: 这个就在规定文本文件实现;

AirPods 4 All In One

AirPods 4 All In One AirPods 4 (支持主动降噪) 优点 有主动降噪功能 缺点 与 AirPods 2 对比,耳机柄变短了,不方便佩戴、取下AirPods 4 All In OneAirPods 4 (支持主动降噪)优点有主动降噪功能缺点与 AirPods 2 对比,耳机柄变短了,不方便佩戴、取下(捏不住)demos免费镌刻…