【GDKOI 2024 TG Day2】不休陀螺(top) 题解
考虑一个卡牌区间怎样才不是“陀螺无限”。
一个是费用在打到一半时费用就不够了。考虑构造一个卡牌序列使其尽量能够在打到一半时费用就不够,如何构造呢?
把 \(a_i > b_i\) 的卡牌称作消耗型卡牌,其他叫做获得型卡牌。我们可以构造把消耗型卡牌全部放在前面,后面突然来个很大的 \(a_i\) 就可以让你费用耗尽了。
但是我们不能贪心地选择,因为假如我们选择这个突然来的很大的 \(a_i\) 也是一个很大的消耗型卡牌,如果把它作为“引火线”就会导致前面消耗的费用不够多,这个导火线也就导不了火。
其实我们可以储存 \(E-a_i\) 表示在使用这张卡片前最多能够消耗的费用,假如一个区间其余的消耗型卡牌起作用使得 \(E-a_i-\text{其他消耗型卡牌的消耗}<0\),那么这个区间就不是”陀螺无限“。这个可以拿线段树维护。
我们只需要枚举区间左端点,然后计算最大的右端点,这个区间内的所有卡牌区间就都是合法方案了,\(O(n^2)\)。
我们会发现,左端点向右移动一位后,对区间内的影响是什么?
如果这个左端点是个消耗型卡牌,那么区间的消耗都会补回这个消耗,这个区间可能合法了,右端点可能可以往右移动;如果左端点是获得性卡牌,对区间没有任何影响。
这说明右端点是递增的,可以均摊 \(O(n)\) 得到合法区间。
另外一个卡牌区间不是”陀螺无限“是这个区间的代价 \(\sum b_i-\sum a_i<0\),这样就算打完一周后总费用也会减少,那么以此类推会越来越少。
这个比较简单,可以维护代价前缀和,也就是求 \(s_i-s_{j-1}\ge0\) 区间个数,即 \(s_i\ge s_{j-1}\),这个可以树状数组维护。
#include <cstdio>
#include <algorithm>
#define ll long long
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define N 1000010
using namespace std;
ll n, e, ans, len;
ll a[N], b[N], c[N]; // ci表示第i个会被扣掉多少
ll s[N], ss[N], to[N];
ll t[4*N]; // 维护每个位置的数能扣多少
ll lazy[4*N];
inline ll min(ll x, ll y) {
return x > y ? y : x;
}
void pushup(ll pos) {
t[pos] = min(t[ls(pos)], t[rs(pos)]);
}
void pushdown(ll pos) {
t[ls(pos)] += lazy[pos];
t[rs(pos)] += lazy[pos];
lazy[ls(pos)] += lazy[pos];
lazy[rs(pos)] += lazy[pos];
lazy[pos] = 0;
}
void update(ll nl, ll nr, ll l, ll r, ll pos, ll k) {
if(nl > nr) return;
if(nl <= l && r <= nr) {
t[pos] += k; // 维护最小值
lazy[pos] += k;
return;
}
if(lazy[pos]) {
pushdown(pos);
}
ll mid = (l + r) >> 1;
if(nl <= mid) {
update(nl, nr, l, mid, ls(pos), k);
}
if(mid < nr) {
update(nl, nr, mid+1, r, rs(pos), k);
}
pushup(pos);
}
ll query(ll nl, ll nr, ll l, ll r, ll pos) {
if(nl <= l && r <= nr) {
return t[pos];
}
if(lazy[pos]) {
pushdown(pos);
}
ll mid = (l + r) >> 1;
ll res = 1e15;
if(nl <= mid) {
res = min(res, query(nl, nr, l, mid, ls(pos)));
}
if(mid < nr) {
res = min(res, query(nl, nr, mid+1, r, rs(pos)));
}
return res;
}
// 桶
ll tong[N];
inline ll lowbit(ll x) {
return x & (-x);
}
void update1(ll x, ll val) {
while(x<=len) {
tong[x] += val;
x += lowbit(x);
}
}
ll query1(ll x) {
ll res=0;
while(x) {
res += tong[x];
x -= lowbit(x);
}
return res;
}
ll read() {
ll x = 0;
char c = '.';
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') {
x = (x<<1)+(x<<3)+(c^'0');
c = getchar();
}
return x;
}
int main() {
freopen("top.in", "r", stdin);
freopen("top.out", "w", stdout);
n =read(),e=read();
for(ll i = 1; i <= n; i++) a[i] = read();
for(ll i = 1; i <= n; i++) b[i] = read();
for(ll i = 1; i <= n; i++) c[i] = a[i] - b[i]; // 反过来好处理
for(ll i = 1; i <= n; i++) {
s[i] = s[i-1];
s[i] -= c[i];
ss[i+1] = s[i]; // 离散化使用
}
// 离散化
sort(ss+1, ss+1+n+1); // 把0也离散化
len = unique(ss+1, ss+1+n+1)-ss-1;
for(ll i = 0; i <= n; i++) {
ll l = 1, r = len; // 考场上不会用lower_bound
while(l <= r) {
ll mid = (l + r) >> 1;
if(ss[mid] < s[i]) l = mid+1;
if(ss[mid] > s[i]) r = mid-1;
if(ss[mid] == s[i]) {
to[i] = mid;
break;
}
}
}
ll r = 1;
bool flag = 0; // 表示已经加入过r了,不用再加入了
ll cost = 0;
for(ll l = 1; l <= n; l++) {
for(; r <= n; r++, flag=0) {
if(!flag) {
if(c[r] > 0) update(l, r-1, 1, n, 1, -c[r]); // 因为加入了r,前面的数都要多扣一个r
update(r, r, 1, n, 1, e - a[r] - cost);
if(c[r] > 0) cost += c[r]; // 把这一位加入cost
flag = true;
update1(to[r], 1);
}
if(query(l, r, 1, n, 1) < 0) { // 如果存在一种方式扣完,那就没了
break;
}
// printf("%lld %lld\n", l, r);
}
// 原本是求l到r内有多少个i使得 s[i]-s[l-1]>=0,也就是有多少个 s[i]>=s[l-1]
// for(ll i = l; i < r; i++) {
// if(s[i] - s[l-1] >= 0) {
// ans++;
// printf("%lld %lld\n", l, i);
// }
// }
if(r <= n) update1(to[r], -1); // 第r位被剔除,所以第r位是不合法的
ans += query1(len) - query1(to[l-1]-1);
if(r <= n) update1(to[r], 1);
// 要剔除最左边那个cost
if(c[l] > 0) cost -= c[l];
if(c[l] > 0) update(l+1, r, 1, n, 1, c[l]);
// 把这l踢出桶
update1(to[l], -1);
}
printf("%lld", ans);
}
【GDKOI 2024 TG Day2】不休陀螺(top) 题解的更多相关文章
- 【转】TYVJ 1695 计算系数(NOIP2011 TG DAY2 1)
计算系数 题目描述 给定一个多项式(ax + by)k,请求出多项式展开后xn ym项的系数. [数据范围] 对于 30%的数据,有0≤k≤10: 对于 50%的数据,有a = 1,b = 1: 对于 ...
- 2019.11.12&13题解
写在前面: 虽然拿到了rk1,但是T3被卡常TLE90分,(考后再交就A了!?),lemon80,又丢失了一次良好的AK机会, 掐头去尾距离联赛仅剩2天,最近中午一直睡不好,可能是有些紧张, 希望自己 ...
- CH Round #58 - OrzCC杯noip模拟赛day2
A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...
- CH Round #49 - Streaming #4 (NOIP模拟赛Day2)
A.二叉树的的根 题目:http://www.contesthunter.org/contest/CH%20Round%20%2349%20-%20Streaming%20%234%20(NOIP 模 ...
- CH Round #55 - Streaming #6 (NOIP模拟赛day2)
A.九九归一 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2355%20-%20Streaming%20%236%20(NOIP模拟赛day2)/九九归一 题 ...
- 题解【洛谷P1315】[NOIP2011]观光公交
题目描述 风景迷人的小城 Y 市,拥有 \(n\) 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务. 观光公交车在第 \(0\) 分钟出现在 \( ...
- 【数论】洛谷P1313计算系数
题目描述 给定一个多项式(by+ax)^k,请求出多项式展开后x^n*y^m 项的系数. 输入输出格式 输入格式: 输入文件名为factor.in. 共一行,包含5 个整数,分别为 a ,b ,k , ...
- MATLAB-卡尔曼滤波简单运用示例
1.角度和弧度之间的转换公式? 设角度为 angle,弧度为 radian radian = angle * pi / 180; angle = radian * 180 / pi; 所以在matla ...
- NOIp2018 pj 滚粗记
NOIp2018 pj 滚粗记 考前 一个午觉睡完就到了考场 考中 \(T1\)水题切了 \(T2\)水题切了 \(T3\)好像是\(dp\),不会,先跳 \(T4\)像树上莫队一样,然后再欧拉序上面 ...
- 哈希Hash在字符串中的应用_C++
本文含有原创题,涉及版权利益问题,严禁转载,违者追究法律责任 哈希大家都会用撒,字符串显然都会写撒,那么哈希离散化字符串不就懂了?!(XXX的神逻辑,其实原文是:树都晓得吧,数组显然都会开呀,那么恭喜 ...
随机推荐
- 50HZ陷波器的原理和实物开发设计
原理 陷波滤波器指的是一种可以在某一个频率点迅速衰减输入信号,以达到阻碍此频率信号通过的滤波效果的滤波器.陷波滤波器属于带阻滤波器的一种,只是它的阻带非常狭窄,起阶数必须是二阶(含二阶)以上. ...
- windows通过cmd重启网卡
ipconfig/release ipconfig/renew
- TypeScript必知三部曲(二)JSX的编译与类型检查
在本三部曲系列的第一部中,我们介绍了TypeScript编译的两种方案(tsc编译.babel编译)以及二者的重要差异,同时分析了IDE是如何对TypeScript代码进行类型检查的.该部分基本涵盖了 ...
- 记录--基于Vue2.0实现后台系统权限控制
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 基于Vue.js 2.x系列 + Element UI 的后台系统权限控制 前言:关于vue权限路由的那些事儿-- 项目背景:现有一个后台 ...
- 大模型时代的PDF解析工具
去年(2023年)是大模型爆发元年.但是大模型具有两个缺点:缺失私有领域知识和幻觉.缺失私有领域知识是指大模型训练时并没有企业私有数据/知识,所以无法正确回答相关问题.并且在这种情况下,大模型会一本正 ...
- 这里有你不得不了解的Java 11版本特性说明
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- 01-【HAL库】STM32实现串口打印
一.什么是串口 串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输 ...
- LOTO任意波形发生器SIG82模拟输出继电器吸合断开的信号波形用于算法调试
LOTO任意波形发生器SIG82模拟输出继电器吸合断开的信号波形用于算法调试 继电器吸合的电流变化过程是如图这样的波形,0到2的时间大约为17毫秒,2到3的时间大约38毫秒. 批量继电器产品吸合是否满 ...
- FineReport 自定义工具栏样式
虽然FR界面的工具栏已经很商业化,很好看了,但是总会有那么些需求希望你可以修改工具栏的样式. 修改工具栏样式的主要思路是: 通过JQ选择器选中需要调整的元素,然后修改他们的样式 接下来,我们尝试着对工 ...
- archlinux 时移(timeshift)不会自动创建快照
这是因为没有开启定时任务服务 解决办法 1.安装定时任务服务 sudo pacman -S cronie 2.设置自启动 sudo systemctl enble cronie