题解:P9353 [JOI 2023 Final] 现代机器 / Modern Machine

news/2026/1/18 23:46:32/文章来源:https://www.cnblogs.com/LUlululu1616/p/19499487

感觉很好的题啊。

题意:感觉总结不是很总结地明白,直接看题面吧。

Bitaro 收到了一个 JOI 机器作为生日礼物。

JOI 机器由一个球、\(N\) 个灯光瓷砖和 \(M\) 个按钮组成。灯光瓷砖从 \(1\)\(N\) 编号。当 Bitaro 打开电源时,灯光瓷砖 \(i\) (\(1 \leq i \leq N\)) 会发出颜色为 \(C_i\)(蓝色(\(\texttt B\))或红色(\(\texttt R\)))的光。按钮从 \(1\)\(M\) 编号。

如果 Bitaro 按下按钮 \(j\) (\(1 \leq j \leq M\)),会发生以下情况。

  1. 球被放置在灯光瓷砖 \(A_j\) 上。
  2. 灯光瓷砖 \(A_j\) 变为红色(无论其原始颜色如何)。
  3. 在球被移除之前,执行以下操作。 设 \(p\) 为球当前所在的灯光瓷砖的索引。
    • 如果灯光瓷砖 \(p\) 是蓝色的,灯光瓷砖 \(p\) 变为红色。之后,如果 \(p = 1\),球被移除。否则,球移动到灯光瓷砖 \(p - 1\)
    • 如果灯光瓷砖 \(p\) 是红色的,灯光瓷砖 \(p\) 变为蓝色。之后,如果 \(p = N\),球被移除。否则,球移动到灯光瓷砖 \(p + 1\)

Bitaro 对 JOI 机器很感兴趣。他计划进行 \(Q\) 次实验。在第 \(k\) 次实验中(\(1 \leq k \leq Q\)),在 Bitaro 打开电源后,Bitaro 按顺序按下按钮 \(L_k, L_{k} + 1, \dots , R_k\)。在 Bitaro 按下一个按钮后,他不会按下下一个按钮,并等待球被移除。

给定 JOI 机器的信息和实验,编写一个程序来计算每次实验结束时颜色为红色的灯光瓷砖的数量。

做法:

首先我们先来看看这个操作会对序列产生什么影响,发现他是往右找到第一个蓝色再找到左边第一个红色轮流轮流这样的,模拟几下,发现操作等于前 \(i\) 个蓝染红和后 \(n-i+1\) 个红染蓝,并且因为整个序列中不能同时存在 \(i\) 个蓝和 \(n-i+1\) 个红,所以可以从整个序列的情况直接快速计算我现在是哪种情况。

直接模拟容易做到 \(O(nmq)\)。然后啥也不会了,让我们看看部分分。

部分分里有一档是前缀是红色,后缀是蓝色,我们发现这种情况下这个结构不会变化,仍然会保证前缀红后缀蓝的情况。我们分讨一下情况,假设前 \(k\) 个是红色,修改位置为 \(p\)

  1. \(p\le k\):如果 \(n-k \ge p\),那么 \(k\to k+p\);否则 \(k\to k-(n-p+1)\)

  2. \(p>k\):如果 \(n-k-1\ge p\),那么 \(k\to k+p+1\),因为还多把 \(p\) 这个位置多变成红色;否则 \(k\to k-(n-p)\)

我们发现一个很好的事情,考虑对这个东西模 \(n+1\),那么就变成:

  • \(k < p\),那么 \(k\to k+p+1\)

  • \(k\ge p\),那么 \(k\to k+p\)

这个东西可以直接维护分段函数,因为他等于一个线段平移,维护每个区间的结尾和加了多少可以方便维护。还有一个做法是我们直接把区间离线下来,然后 fhq 维护平移也可以,我写的是分段函数的写法。

但是这是部分分做法,我们多数时候当然不满足这个条件。我们考虑维护目前最左端连续的红色,右端的蓝色长度分别为 \(x,y\)。我们发现,如果修改位置为 \(x<p\le n-y\),那么好处是 \(x,y\) 中有一个翻倍,这很好,操作次数是 \(\log\) 的。但是比如,\(x=y=1\),我一直操作 \(p=1\),那么次数就变成 \(n\)。但是有一个好处,如果落在 \([1,x],[n-y+1,n]\) 的范围内,如果落在前者,那么一定是把 \(x\) 增大,否则一定把 \(y\) 增大,这个事情让我们可以直接去找到 \([x+1,n-y]\) 中下一个操作的位置,其他的我们可以 \(O(1)\) 计算,你可以采用主席树的方式来找,就是按操作序列从后往前扫,维护每个位置上一次出现位置即可。但是还有一个做法,我们可以考虑倍增分块,这样我们就只用维护 \(\log^2n\) 种区间情况下一次操作的位置,并且这样同样次数还是 \(\log n\) 的,我写的是倍增分块的做法。

然后大概就做完了,有一些蓝红色的分讨注意一下就可以了。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5, V = 21;
int n, m, id[maxn], a[maxn], q;
struct Seg {int ed, k;friend bool operator<(Seg x, Seg y) {return x.ed < y.ed;}
};
struct Segtree {vector<Seg> tr[maxn << 2];void build(int l, int r, int t) {if(l == r) {if(a[l] == n)tr[t].push_back(Seg{n - 1, 0}), tr[t].push_back(Seg{n, -1});else if(a[l] * 2 > n)tr[t].push_back(Seg{n - a[l] - 1, a[l] + 1}),tr[t].push_back(Seg{a[l] - 1, a[l] + 1 - (n + 1)}),tr[t].push_back(Seg{n, a[l] - (n + 1)});elsetr[t].push_back(Seg{a[l] - 1, a[l] + 1}),tr[t].push_back(Seg{n - a[l], a[l]}),tr[t].push_back(Seg{n, a[l] - (n + 1)});return ;}int mid = l + r >> 1;build(l, mid, t << 1), build(mid + 1, r, t << 1 | 1);int L = 0, R, v;for (int i = 0; i < tr[t << 1].size(); i++) {R = tr[t << 1][i].ed, v = tr[t << 1][i].k;int bg = lower_bound(tr[t << 1 | 1].begin(), tr[t << 1 | 1].end(), Seg{L + v, 0}) - tr[t << 1 | 1].begin();int ed = lower_bound(tr[t << 1 | 1].begin(), tr[t << 1 | 1].end(), Seg{R + v, 0}) - tr[t << 1 | 1].begin();for (bg; bg < ed; bg++)tr[t].push_back(Seg{tr[t << 1 | 1][bg].ed - v, v + tr[t << 1 | 1][bg].k});tr[t].push_back(Seg{R, v + tr[t << 1 | 1][ed].k}), L = R + 1;}//	cout << l << " " << r << " " << tr[t][tr[t].size() - 1].ed << " " << L << " " << R << endl;}void query(int l, int r, int x, int y, int t, int &p) {if(x <= l && r <= y) {int pos = lower_bound(tr[t].begin(), tr[t].end(), Seg{p, 0}) - tr[t].begin();//	cout << pos << " " << tr[t].size() << endl;p += tr[t][pos].k;return ;}	int mid = l + r >> 1;if(x <= mid)query(l, mid, x, y, t << 1, p);if(mid < y)query(mid + 1, r, x, y, t << 1 | 1, p);}
} tree;
int lx[maxn], lp[maxn], rx[maxn], rp[maxn], lt, rt, lg[maxn], s[maxn];
int nxt[V][V][maxn], sl[V][V][maxn], sr[V][V][maxn];
void prepare() {for (int i = 1; i <= n + 1; i++) {if(id[i] != 1)lx[++lt] = i - 1,lp[i - 1] = lt;}for (int i = n; i >= 0; i--)if(id[i] != 0) {rx[++rt] = n - i,rp[i] = rt;//cout << rt << " " << i << " " << rx[1] << endl;}
//	cout << rx[1] << "asdlkfjsadlkfjsadkfjfdg " << lx[1] << endl;lg[0] = 0;for (int i = 1; i <= n; i++)lg[i] = lg[i >> 1] + 1, s[i] = s[i - 1] + (!id[i]);for (int tx = 0; tx <= V - 1; tx++)for (int ty = 0; ty <= V - 1; ty++) {int x = (tx == 0 ? 0 : (1 << tx - 1)), y = (ty == 0 ? 0 : (1 << ty - 1));nxt[tx][ty][m + 1] = m + 1;for (int i = m; i >= 1; i--) {if(a[i] > x && a[i] <= n - y)nxt[tx][ty][i] = i;elsenxt[tx][ty][i] = nxt[tx][ty][i + 1];}for (int i = 1; i <= m; i++)sl[tx][ty][i] = sl[tx][ty][i - 1] + (a[i] <= x ? a[i] : 0),sr[tx][ty][i] = sr[tx][ty][i - 1] + (a[i] > n - y ? n - a[i] : 0);}
//	cout << nxt[0][0][1] << "  " << lx[1] << " " << rx[1] << endl;
}
int main() {
//	freopen("test.in", "r", stdin);
//	freopen("std.out", "w", stdout);cin >> n >> m;for (int i = 1; i <= n; i++) {char c; cin >> c; id[i] = c == 'R';//	cout << "adf" << endl;}id[0] = -1; id[n + 1] = -1;for (int i = 1; i <= m; i++)cin >> a[i];//cout << "adf" << endl;tree.build(1, m, 1);prepare();cin >> q;while(q--) {int l, r; cin >> l >> r;int L = l - 1, R, x = 1, y = 1, qry = -1;while(1) {int X = lg[lx[x]], Y = lg[rx[y]];R = min(r + 1, nxt[X][Y][L + 1]); R--;//	cout << L << " " << R << " " << " " << X << " " << Y << " " << lx[x] << " " << rx[y] << " " << x << " " << y << endl;int sx = x + sl[X][Y][R] - sl[X][Y][L], sy = y + sr[X][Y][R] - sr[X][Y][L];//	cout << lx[min(sx, lt)] << " " << rx[min(sy, rt)] << " " << sx << " " << sy << " " << rx[sy] << endl;//	cout << L << " " << R << " " << sx << " " << sy << " " << lx[sx] << " " << rx[sy] << endl;if(lx[min(sx, lt)] + rx[min(sy, rt)] < n) {x = sx, y = sy; L = R + 1;//	cout << L << " laskdgjsag" << R << " " << x << " " << y << endl;if(L == r + 1) {//		cout << "asdf" << endl;break;}int sum = s[n - rx[y]] - s[lx[x]] + rx[y];int pos = a[L] + (a[L] >= n - rx[y] + 1 ? 1 : (a[L] <= lx[x] ? 0 : !id[a[L]]));//	cout << sum << " " << pos << endl;if(pos <= sum) {if(pos >= sum - rx[y]) {L = L + 1;qry = n - rx[y] + (pos - (sum - rx[y]));break;}elsex += pos;}else {sum = n - sum, pos = (n - a[L] + (a[L] >= n - rx[y] + 1 ? 0 : (a[L] <= lx[x] ? 1 : id[a[L]])));//	cout << pos << endl;if(pos >= sum - lx[x]) {L = L + 1;qry = lx[x] -  (pos - (sum - lx[x]));break;}elsey += pos;}}else {int lpos = L, rpos = R;while(lpos + 1 < rpos) {int mid = lpos + rpos >> 1;sx = x + sl[X][Y][mid] - sl[X][Y][L], sy = y + sr[X][Y][mid] - sr[X][Y][L];if(lx[min(sx, lt)] + rx[min(sy, rt)] < n) lpos = mid;elserpos = mid;}R = lpos;sx = x + sl[X][Y][R] - sl[X][Y][L], sy = y + sr[X][Y][R] - sr[X][Y][L];x = sx, y = sy; L = R + 1;if(L == r + 1)break;int sum = s[n - rx[y]] - s[lx[x]] + rx[y];int pos = a[L] + (a[L] >= n - rx[y] + 1 ? 1 : (a[L] <= lx[x] ? 0 : !id[a[L]]));if(pos <= sum) {if(pos >= sum - rx[y]) {L = L + 1;qry = n - rx[y] + (pos - (sum - rx[y]));break;}elsex += pos;}else {sum = n - sum, pos = (n - a[L] + (a[L] >= n - rx[y] + 1 ? 0 : (a[L] <= lx[x] ? 1 : id[a[L]])));//	cout << pos << " " << sum << " " << y << " " << x << endl;if(pos >= sum - lx[x]) {L = L + 1;qry = lx[x] -  (pos - (sum - lx[x]));break;}elsey += pos;}break;}}//	cout << x << " " << y << " " << lx[x] << " " << rx[y] << " " << L << " " << r << endl;if(qry == -1) {//		cout << s[n - rx[y]] << "adf " << s[lx[x]] << " " << lx[x] << " " << n - rx[y] << endl;int sum = s[n - rx[y]] - s[lx[x]] + rx[y];cout << n - sum << endl;}else {//	cout << L << " " << r << " " << qry << endl;if(L <= r)tree.query(1, m, L, r, 1, qry);cout << qry << endl;}}return 0;
}
/*
10 10
RRRRRRRRRR
4 7 5 10 6 7 5 2 1 3 
1
1 9
*/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

12款论文AI工具横向对比:数学建模论文复现效率提升与格式优化方法

还在为论文写作头痛&#xff1f;特别是数学建模的优秀论文复现与排版&#xff0c;时间紧、任务重&#xff0c;AI工具能帮上大忙吗&#xff1f;今天&#xff0c;我们评测10款热门AI论文写作工具&#xff0c;帮你精准筛选最适合的助手。 aibiye&#xff1a;专注于语法润色与结构…

12款论文AI工具横向对比:数学建模论文复现效率提升与格式优化方法

还在为论文写作头痛&#xff1f;特别是数学建模的优秀论文复现与排版&#xff0c;时间紧、任务重&#xff0c;AI工具能帮上大忙吗&#xff1f;今天&#xff0c;我们评测10款热门AI论文写作工具&#xff0c;帮你精准筛选最适合的助手。 aibiye&#xff1a;专注于语法润色与结构…

12款AI论文工具深度分析:数学建模论文快速复现与格式精准调整方案

还在为论文写作头痛&#xff1f;特别是数学建模的优秀论文复现与排版&#xff0c;时间紧、任务重&#xff0c;AI工具能帮上大忙吗&#xff1f;今天&#xff0c;我们评测10款热门AI论文写作工具&#xff0c;帮你精准筛选最适合的助手。 aibiye&#xff1a;专注于语法润色与结构优…

12款AI论文工具深度分析:数学建模论文快速复现与格式精准调整方案

还在为论文写作头痛&#xff1f;特别是数学建模的优秀论文复现与排版&#xff0c;时间紧、任务重&#xff0c;AI工具能帮上大忙吗&#xff1f;今天&#xff0c;我们评测10款热门AI论文写作工具&#xff0c;帮你精准筛选最适合的助手。 aibiye&#xff1a;专注于语法润色与结构优…

XDP与eBPF:Linux网络性能优化实战指南

1.XDP与eBPF&#xff1a;Linux网络性能优化实战指南 掌握 XDP&#xff08;eXpress Data Path&#xff09;和 eBPF&#xff08;extended Berkeley Packet Filter&#xff09;的使用与开发&#xff0c;是深入 Linux 网络、安全、可观测性等领域的重要技能。以下是系统性的学习路…

12款智能论文写作工具全面评测:数学建模论文高效还原与专业排版优化策略

还在为论文写作头痛&#xff1f;特别是数学建模的优秀论文复现与排版&#xff0c;时间紧、任务重&#xff0c;AI工具能帮上大忙吗&#xff1f;今天&#xff0c;我们评测10款热门AI论文写作工具&#xff0c;帮你精准筛选最适合的助手。 aibiye&#xff1a;专注于语法润色与结构…

9D VR体验馆设备多少钱的投资分析与运营策略探讨

9D VR体验馆设备投资成本详解与市场分析 在考虑9D VR体验馆设备的投资成本时&#xff0c;首先需要评估几个关键因素&#xff0c;包括设施建设、设备采购及日常运营等方面。通常&#xff0c;初期投资大约在10万至15万元之间&#xff0c;这包括了VR双人蛋椅、VR魔力互动设备和VR3…

从用户体验到提示工程:架构师分享如何将UX研究方法应用于提示词优化

从用户体验到提示工程:架构师分享如何将UX研究方法应用于提示词优化 关键词 UX研究、提示工程、用户需求、交互设计、AI提示优化、用户旅程地图、Persona 摘要 当我们谈论AI交互时,“提示词”就像一把钥匙——它决定了AI能否听懂你的需求,能否输出符合预期的结果。但现实…

12款智能论文辅助工具评测:数学建模论文精准复现与专业排版优化策略

还在为论文写作头痛&#xff1f;特别是数学建模的优秀论文复现与排版&#xff0c;时间紧、任务重&#xff0c;AI工具能帮上大忙吗&#xff1f;今天&#xff0c;我们评测10款热门AI论文写作工具&#xff0c;帮你精准筛选最适合的助手。 aibiye&#xff1a;专注于语法润色与结构…

12款智能论文辅助软件测评:数学建模论文快速复现与格式精细调整指南

还在为论文写作头痛&#xff1f;特别是数学建模的优秀论文复现与排版&#xff0c;时间紧、任务重&#xff0c;AI工具能帮上大忙吗&#xff1f;今天&#xff0c;我们评测10款热门AI论文写作工具&#xff0c;帮你精准筛选最适合的助手。 aibiye&#xff1a;专注于语法润色与结构优…

基于51/STM32单片机太阳能路灯台灯光伏风能追光光通信无线设计(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

09-太阳能光伏 基于51/STM32单片机太阳能路灯台灯光伏风能追光可见光通信无线设计 太阳能板风能风机充电管理升压锂电池光敏高亮LEDC51-19 WIFI无线太阳能板充电管理升压锂电池光敏AD转换高亮LEDPWM档位C51-21 蓝牙无线太阳能板充电管理升压锂电池光敏AD转换高亮LEDPWM档位C51-…

12款AI论文工具对比分析:数学建模论文高效重现与专业排版优化策略

还在为论文写作头痛&#xff1f;特别是数学建模的优秀论文复现与排版&#xff0c;时间紧、任务重&#xff0c;AI工具能帮上大忙吗&#xff1f;今天&#xff0c;我们评测10款热门AI论文写作工具&#xff0c;帮你精准筛选最适合的助手。 aibiye&#xff1a;专注于语法润色与结构…

基于51/STM32单片机老人防跌智能拐杖GSM短信北斗定位地图无线设计(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

15-跌倒报警拐杖 基于51/STM32单片机老人防跌智能拐杖GSM短信北斗定位地图无线设计 跌倒状态检测蜂鸣器报警C51-13 蓝牙无线跌倒状态检测蜂鸣器报警C51-14 GSM短信远程心率DS1302时钟校时监控状态LCD1602液晶按键C51-105 GSM短信远程跌倒状态检测蜂鸣器报警灯指示按键防误报号码…

12款智能写作助手评测:数学建模论文精准复现与格式优化完整方案

AI工具已成为数学建模论文写作的高效助手&#xff0c;尤其在复现优秀论文和精准排版方面表现突出。本次评测聚焦10款热门AI写作工具&#xff0c;从代码生成、公式编辑到排版优化进行深度对比&#xff0c;帮助研究者快速匹配最适合的解决方案&#xff0c;显著提升学术产出效率。…

12款AI论文写作软件深度测评:数学建模论文高效还原与排版优化技巧

还在为数学建模论文的复现和排版焦头烂额&#xff1f;AI工具能高效解决时间紧迫、任务繁重的问题。本文深度评测10款热门AI论文写作工具&#xff0c;从代码生成、公式排版到逻辑优化&#xff0c;助你快速匹配最适合的智能助手&#xff0c;轻松攻克学术难关。 aibiye&#xff1…

基于51/STM32单片机智能台灯灯光控制PWM调光语音识别坐姿设计(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

51-C01-人走灯灭AD采集自动手动10档调节坐姿监测蜂鸣器OLED屏(无线方式选择) 51-C01N无无线-无APP板: 51-C01B蓝牙无线-APP版: 51-C01W-WIFI无线-APP版: 51-C01CAN-视频监控WIFI无线-APP版: 产品功能描述&#xff1a; 本系统由STC89C52单片机最小系统电路、OLED液晶显示、&…

两步实现在ThinkLink平台上的告警功能

1. 功能概述 ThinkLink 的告警通知功能是基于平台强大的 RPC (Remote Procedure Call) 机制 实现的。通过将告警逻辑封装在触发联动模型中&#xff0c;平台能够根据设备上报的数据实时判断是否达到告警条件&#xff0c;并调用预设的 alarm 类型 RPC 消息&#xff0c;实现告警的…

Windows 11 + WSL2 + vLLM 本地部署 Qwen3 8B AWQ 指南

Windows 11 WSL2 vLLM 本地部署 Qwen3 8B AWQ 指南 目录 系统要求环境准备WSL2 Ubuntu 安装配置NVIDIA 驱动配置CUDA 环境安装Python 环境搭建vLLM 安装Qwen3 8B AWQ 模型下载&#xff08;国内加速&#xff09;启动 vLLM 服务API 测试验证常见问题解决性能优化建议 系统要求…

导师严选!专科生必看8款AI论文平台测评

导师严选&#xff01;专科生必看8款AI论文平台测评 2026年专科生论文写作工具测评&#xff1a;为何需要这份榜单&#xff1f; 随着AI技术在学术领域的广泛应用&#xff0c;越来越多的专科生开始借助AI平台提升论文写作效率。然而&#xff0c;面对市场上五花八门的AI论文工具&am…

基于51/STM32单片机智能水杯保温杯恒温温度控制防干烧水质设计(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

STM32-S264-水量监测保温常温温度灯光指示定时提醒定时开关加热防干烧参数可设OLED屏声光提醒(无线方式选择)STM32-S264N无无线-无APP板(硬件操作详细): STM32-S264B蓝牙无线-APP版: STM32-S264W-WIFI无线-APP版: STM32-S264CAN-视频监控WIFI无线-APP版: STM32-S264I-云平台-AP…