题解:P12525 [Aboi Round 1] 私は雨

news/2025/10/21 19:53:12/文章来源:https://www.cnblogs.com/lymsHz17/p/19156283

link

顺带一提这是我第一道没看题解做出来的黑(也是第四道黑)。

写完看了一圈题解,我想说:

欸不是凭啥我不用卡常啊?

前言

这篇题解的复杂度是这样的:

\(p\) \(O(q \sqrt n \log \sqrt n + n \sqrt V)\),大 \(p\) \(O (\sqrt V \log n)\)

没卡常,也没有把 \(\log\) 调到下面什么的,过了。写完后到是卡了卡,暂时在最优解第一页。

正文

首先把值域看成一条直线,我们发现查询的位置的总数直接和 \(p\) 相关,是 \(\lfloor \frac Vq \rfloor\) 次,容易想到根号分治,以 \(\sqrt V\) 作为分治边界。

对于 \(p > \sqrt V\),发现查询的值很少,可以直接存下每一个值的出现位置,存成一个个序列,然后在这些序列上二分,就可以得到答案。

这里给出实现:

vector<int> pos[V]; // 每一个值的序列// 查询
inline int query_ma(int l, int r, int vl, int vr, int p, int x) {int que = (vl - x + p - 1) / p * p + x, res = 0;while(que <= vr) {if(pos[que].size()) res += upper_bound(pos[que].begin(), pos[que].end(), r) - lower_bound(pos[que].begin(), pos[que].end(), l);que += p;} return res;
}......
......
//(main 里面)存储
for(int i = 1; i <= n; i ++) pos[in(a[i])].push_back(i);

对于 \(p \le \sqrt V\),可以对着序列分块,然后直接强行预处理某块内对模数 \(p\) 取模得数为 \(b\) 的值,全都压到一个 vector 里面,查询的时候仍旧二分查找,不过这次二分的内容是值域。

然后就发现会 MLE,很凄惨,所以干脆就分治边界开小一点,序列分块块长开大一点,让暴力多跑一点,复杂度是不纯粹了,不过还是能过的。

这一步实现比较长,一会看完整代码吧。

然后是一些卡常技巧,毕竟一会要放的是我卡过常数的代码。

首先是 vector 的插入的常数非常大,大概是因为要动态分配内存,所以考虑先跑一遍你要插的数,求出每一个 vector 的大小,然后先 reverse 一下,就会飞快。

然后是查询,一般人都会散块跑暴力对吧,这是对的,但是可以优化,可以比较一个块左右端点和查询位置的距离,只跑小的那一边,如果跑的不是我们想要的,就加上整块,容斥一下,这样可以把(普通分块的)查询从最劣 \(3\sqrt n\) 做成 最劣 \(2\sqrt n\),会快很多,在这里因为整块查询是带 \(\log\) 的,所以算距离的时候要带上查整块的代价,会更快一点。

再然后是我看最上面和我做法(应该)一样的那个题解,\(p\) 小的部分他对每一块都 sort 了,而这一步显然可以通过使插入的数字提前有序而省去。

再再然后是注意操作的空间要连续,不然大概会慢,没试,我一开始写空间就是连续的。

最后是玄学调块长,很奇怪但是值域的分治边界改成 \(100\) 会快到飞起(作为对比我一开始是 \(200\))。

完整代码

// code by 樓影沫瞬_Hz17
#include <bits/stdc++.h>
using namespace std;#define getc() getchar_unlocked()
#define putc(a) putchar_unlocked(a)
#define en_ putc('\n')
#define e_ putc(' ')using pii = pair<int, int>;template<class T> inline T in() { T n = 0; char p = getc();while(p < '-') p = getc();bool f = p == '-' ? p = getc() : 0;do n = n * 10 + (p ^ 48), p = getc();while(isdigit(p));return f ? -n : n;
}
template<class T> inline T in(T &a) { return a = in<T>(); }
template<class T, class ... Args> inline void in(T &t, Args&... args) { in(t), in(args...); }template<class T> inline void out(T n) {if(n < 0) putc('-'), n = -n;if(n > 9) out(n / 10);putc(n % 10 + '0');
}template<class T1, class T2> T1 max(T1 a, T2 b) { return a > b ? a : a = b;}
template<class T1, class T2> T1 min(T1 a, T2 b) { return a < b ? a : a = b;}constexpr int N = 1e5 + 10, B = 370, T = N / B + 10, V = 2e5 + 10, D = 100, M = N / D + 10;int n, a[N], ans, q;
bool type;vector<int> pos[V];int L[T], R[T], bel[N];
// 大p的查询
inline int query_ma(int l, int r, int vl, int vr, int p, int x) {int que = (vl - x + p - 1) / p * p + x, res = 0; // que 表示要查的位置,计算方式比较烂while(que <= vr) {if(pos[que].size()) res += upper_bound(pos[que].begin(), pos[que].end(), r) - lower_bound(pos[que].begin(), pos[que].end(), l);que += p;} return res;
}int sz[D][D][T];
vector<int> sum[D][D][T]; // 写到这发现刚好是 DDT 给我笑喷了
// sum[i][j][k] 指在 k 块内对 i 取模为 j 的数
inline int que_mi(vector<int>&q, int vl, int vr) { if(q.empty()) return 0; // 这个是 p 小的时候对整块的查询,用得多,兴许我不写成函数会快?我懒return upper_bound(q.begin(), q.end(), vr) - lower_bound(q.begin(), q.end(), vl);
} 
// 下面是对小 p 的查询
inline int query_mi(int l, int r, int vl, int vr, int p, int x, vector<int> *sm) { int ql = bel[l], qr = bel[r], res = 0;if(qr == ql) { // 同一块其实也能用我讲得那个优化,不过我懒for(int i = l; i <= r; i ++)  if(a[i] % p == x) res += (a[i] <= vr and a[i] >= vl);return res;	} if(R[ql] - l - 14 < l - L[ql]) { // 令 14 作为整块查询的代价,比较是正着快还是容斥快for(int i = l; i <= R[ql]; i ++)  // 正着跑if(a[i] % p == x) res += (a[i] <= vr and a[i] >= vl);} else { res += que_mi(sm[ql], vl, vr); // 容斥for(int i = L[ql]; i < l; i ++) if(a[i] % p == x)res -= (a[i] <= vr and a[i] >= vl);} if(r - L[qr] - 14 < R[qr] - r) { // 同上for(int i = L[qr]; i <= r; i ++) if(a[i] % p == x)res += (a[i] <= vr and a[i] >= vl);} else { res += que_mi(sm[qr], vl, vr);for(int i = r + 1; i <= R[qr]; i ++) if(a[i] % p == x)res -= (a[i] <= vr and a[i] >= vl);} // 整块我没法优化了for(int i = ql + 1; i < qr; i ++) res += que_mi(sm[i], vl, vr);return res;
} struct num { int id, val; };
num b[N]; // 辅助数组inline void get(int &x)  { x ^= type ? ans : 0;}signed main() { #ifndef ONLINE_JUDGE freopen("私は雨.in", "r", stdin);freopen("私は雨.out", "w", stdout);#endif in(n, type);for(int i = 1; i <= n; i ++) pos[in(a[i])].push_back(i);for(int i = 1; i <= n; i ++) { b[i].id = i;b[i].val = a[i];} sort(b + 1, b + 1 + n, [](num a, num b) { return a.val < b.val;});// 排序,然后就不用最后每个块重排了for(int i = 1, j; R[i - 1] != n; i ++) { L[i] = (i - 1) * B + 1, R[i] = min(n, i * B); for(j = L[i]; j <= R[i]; j ++) bel[j] = i;} for(int p = 1; p < D; p ++)  for(int i = 1; i <= n; i ++)  sz[p][a[i] % p][bel[i]] ++; // 预先算 size for(int p = 1; p < D; p ++) for(int j = 0; j < p; j ++) for(int i = 1; R[i - 1] != n; i ++) sum[p][j][i].reserve(sz[p][j][i]); // 然后 reservefor(int p = 1; p < D; p ++)  for(int i = 1; i <= n; i ++)  sum[p][b[i].val % p][bel[b[i].id]].emplace_back(b[i].val);// 如果不这样做的话会慢死的,预处理 TLE 了解一下in(q);for(int i = 1, l, r, L, R, p, x; i <= q; i ++) { in(l, r, L, R, p, x);get(l), get(r), get(L), get(R), get(p), get(x);ans = p >= D ? query_ma(l, r, L, R, p, x) : query_mi(l, r, L, R, p, x, sum[p][x]);out(ans), en_;} 
}   
// 星間~ 干渉~ 融解~ 輪迴~ 邂逅~ 再生~ ララバイ~

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

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

相关文章

完整教程:罗技G102有线鼠标自己维修教程

完整教程:罗技G102有线鼠标自己维修教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "M…

杂谈

代码如下,将这一段代码优化了下 string id = AAA(msg->msg_sender_);if (id.empty()){BBB(msg);VX_INFO_FUN_OUT();return;}#ifdef PROJECT_A//理论上不会到这里,因为id.empty会会处理,这里做一个保护if(U::i…

挖矿-学校挖矿排查

挖矿-学校挖矿排查 1、使用工具分析共有多少IP存在扫描web特征,提交其数量 这里我们直接访问百度网盘将流量下载到本地然后直接导入到 ZUI里面,这个工具很方便对流量进行筛选流量分析工具ZUI安装然后使用命令搜索 co…

读书日记2

四五章深入探讨了软件构建的关键前期工作,让我认识到优秀代码的质量在很大程度上是由设计阶段决定的。 核心收获与深刻见解: 1.设计的层次性思维:McConnell详细阐述了从系统架构到类设计,再到子程序设计的完整层次…

定位问题3:明明堆栈已经打印出来了,偏就是定位不出来?

堆栈如下,明明是在AAA::B函数里core了,而且是概率core的,可就是定位不出来 B函数很简单 1. 第一句打印入参 2. 其它都是函数调用 3. 打印退出消息 对于1 ,参数如下,不可能为nullptr,也排查了调用处(仅2处),不存…

Spring 统一机制处理 - 拦截器与适配器

Spring 统一机制处理 - 拦截器与适配器pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Mon…

鸿蒙hdc命令【杭州多测师】

1、查看版本hdc -v2、查看连接设备hdc list targets3、安装应用hdc app install .\phone-launcher-default-signed.hap// 覆盖安装hdc app install -r .\phone-launcher-default-signed.hap// 安装、更新,多HAP可以指…

电脑黑屏只剩鼠标-解决方案 - 教程

电脑黑屏只剩鼠标-解决方案 - 教程2025-10-21 19:26 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !impo…

如何将海量纸质表格一键数字化?表格识别技术给出答案

在当今的智能办公时代,海量的信息仍被困在纸质文档或僵化的电子图片中,其中,结构复杂、数据密集的表格是信息数字化的主要瓶颈之一。表格识别技术的崛起,正如同一位不知疲倦的“数据捕手”,精准地破解了这一难题,…

10.21 NOIP 模拟赛 T1. 小 h 学步

思路 最终答案为: [ ans = \sum_{i} \left( \left( \sum x_i \right)^2 + \left( \sum y_i \right)^2 + \left( \sum z_i \right)^2 \right) ] 其中对于同一个 ( i, x_i, y_i, z_i ) 互相关联。 将 ( x ) 部分的平方拆…

深入解析:【Linux】生产者消费者模型

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

湖南新建高速项目的“神经网络”是如何搭建的?——揭秘80公里高速的收费、通信、监控一体化系统

湖南新建高速项目的“神经网络”是如何搭建的?——揭秘80公里高速的收费、通信、监控一体化系统湖南省某条贯穿山区、串联景区的高速公路,不仅是交通主干道,更是区域协同发展和旅游经济助推器。全长约80公里,北起湘…

深入解析:大数据Spark(六十六):Transformation转换算子sample、sortBy和sortByKey

深入解析:大数据Spark(六十六):Transformation转换算子sample、sortBy和sortByKeypre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; …

完整教程:web前端团队开发code review方案最佳实践

完整教程:web前端团队开发code review方案最佳实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas"…

实用指南:免费html网页模板 html5网站模板 静态网页模板

实用指南:免费html网页模板 html5网站模板 静态网页模板pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas…

最大值的不同统计方法

题目:CF2154B 2154B 题目中有这样一句话: 操作1: 选择一个整数 i 并执行 : 用最大值为 i的前缀替换 $ a_i $ 。 $$ \sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6} $$

加密货币如何改变金融诈骗的游戏规则

本文深入分析加密货币如何被诈骗分子利用实施新型金融犯罪,揭露了包括虚假赠品网站、匿名钱包洗钱、AI深度伪造等最新诈骗手法,并提供了5种实用防护策略保护个人资产安全。加密货币如何改变金融诈骗的游戏规则 加密货…

leetcode448. 找到所有数组中消失的数字

leetcode448. 找到所有数组中消失的数字448. 找到所有数组中消失的数字我的解法:额外数组class Solution {public List<Integer> findDisappearedNumbers(int[] nums) {int n = nums.length;boolean[] flag = n…

远程服务器显示pyQt界面

远程服务器显示pyQt界面1 vscode+mobaxterm实现服务器图形显示 在服务器上跑深度学习任务是有时候会需要可视化图片,但是服务器一般没有图形显示的功能: $ xclock Error: Cant open display: 可以通过 vscode+mobaxt…

揭开 C++ vector 底层面纱:从三指针模型到手写完整实现 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …