题目大意:有$n(n\leqslant5\times10^5)$个数,$m(m\leqslant5\times10^5)$个询问,每个询问问区间$[l,r]$中众数的出现次数

题解:分块,设块大小为$S$,先可以预处理出两两块之间的众数出现次数,复杂度$O(\Big(\dfrac n S\Big)n)$。询问时先把答案设成整块内的答案,然后对两边剩下的最多$2S$个元素进行讨论。

难点在如何快速求出一个元素在区间内出现次数,先想到的是主席树,但是多了一个$\log_2$,并过不去。可以把每种数出现的位置用$vector$存下来,并且对每个数存一个它在$vector$中的位置,第$i$个数的位置是$ret_i$,假设现在的答案为$ans$,正在处理左边的多余元素,处理到第$i$个,可以看这个数值的$vector$中,第$ret_i+ans$位是否小于$r$,若小于,则这个数至少出现了$ans+1$次,更新答案。右边也是类似的。

发现$ans$最多自增$2S$次,所以一次查询的复杂度是$O(2S)$的,总复杂度为$O(2Sm+\Big(\dfrac n S\Big)n)$,当$S$略小于$\sqrt n$时最优(其实是我不怎么算)

卡点:$Ynoi$当然卡常啦

C++ Code:

#include <algorithm>
#include <cstdio>
#include <cctype>
#include <vector> namespace std {
struct istream {
#define M (1 << 24 | 3)
char buf[M], *ch = buf - 1;
inline istream() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
fread(buf, 1, M, stdin);
}
inline istream& operator >> (int &x) {
while (isspace(*++ch));
for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
return *this;
}
#undef M
} cin;
struct ostream {
#define M (1 << 24 | 3)
char buf[M], *ch = buf - 1;
int w;
inline ostream& operator << (int x) {
if (!x) {
*++ch = '0';
return *this;
}
for (w = 1; w <= x; w *= 10);
for (w /= 10; w; w /= 10) *++ch = (x / w) ^ 48, x %= w;
return *this;
}
inline ostream& operator << (const char x) {*++ch = x; return *this;}
inline ostream& operator << (const char *x) {
while (*x) *this << *x++;
return *this;
}
inline ~ostream() {
#ifndef ONLINE_JUDGE
freopen("output.txt", "w", stdout);
#endif
fwrite(buf, 1, ch - buf + 1, stdout);
}
#undef M
} cout;
} #define maxn 500010
const int BSZ = 610, BNUM = maxn / BSZ + 10; int cnt[maxn];
int MAX[BNUM][BNUM];
int L[maxn], R[maxn], bel[maxn]; int n, m, Bnum;
int w[maxn], v[maxn]; std::vector<int> list[maxn];
int ret[maxn];
int main() {
std::cin >> n >> m;
for (int i = 1; i <= n; i++) {
std::cin >> w[i];
v[i] = w[i];
bel[i] = (i - 1) / BSZ + 1;
} const int tot = (std::sort(v + 1, v + n + 1), std::unique(v + 1, v + n + 1) - v - 1);
for (int i = 1; i <= n; i++) {
w[i] = std::lower_bound(v + 1, v + tot + 1, w[i]) - v;
ret[i] = list[w[i]].size();
list[w[i]].push_back(i);
} Bnum = bel[n];
for (int i = 1; i <= Bnum; i++) {
L[i] = (i - 1) * BSZ, R[i] = L[i] + BSZ - 1;
}
L[1] = 1, R[Bnum] = n;
for (int i = 1; i <= Bnum; i++) {
__builtin_memset(cnt, 0, sizeof cnt);
int Max = 0, now = i;
for (int j = L[i]; j <= n; j++) {
cnt[w[j]]++;
Max = std::max(Max, cnt[w[j]]);
if (j == R[now]) {
MAX[i][now] = Max;
now++;
}
}
} int ans = 0;
while (m --> 0) {
int l, r;
std::cin >> l >> r;
l ^= ans, r ^= ans;
const int lb = bel[l], rb = bel[r];
ans = 0;
if (lb == rb) {
for (int i = l; i <= r; i++) {
const int W = w[i], sz = list[W].size(), pos = ret[i];
while (pos + ans < sz && list[W][pos + ans] <= r) ans++;
}
} else {
if (lb + 1 < rb) ans = MAX[lb + 1][rb - 1];
for (int i = l; i <= R[lb]; i++) {
const int W = w[i], sz = list[W].size(), pos = ret[i];
while (pos + ans < sz && list[W][pos + ans] <= r) ans++;
}
for (int i = L[rb]; i <= r; i++) {
const int W = w[i], pos = ret[i];
while (pos >= ans && list[W][pos - ans] >= l) ans++;
}
}
std::cout << ans << '\n';
}
return 0;
}

  

[洛谷P5048][Ynoi2019模拟赛]Yuno loves sqrt technology III的更多相关文章

  1. 洛谷P5048 [Ynoi2019模拟赛]Yuno loves sqrt technology III(分块)

    传送门 众所周知lxl是个毒瘤,Ynoi道道都是神仙题 用蒲公英那个分块的方法做结果两天没卡过去→_→ 首先我们分块,预处理块与块之间的答案,然后每次询问的时候拆成整块和两边剩下的元素 整块的答案很简 ...

  2. 洛谷 P5048 - [Ynoi2019 模拟赛] Yuno loves sqrt technology III(分块)

    题面传送门 qwq 感觉跟很多年前做过的一道题思路差不多罢,结果我竟然没想起那道题?!!所以说我 wtcl/wq 首先将 \(a_i\) 离散化. 如果允许离线那显然一遍莫队就能解决,复杂度 \(n\ ...

  3. 洛谷 P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I(分块+卡常)

    洛谷题面传送门 zszz,lxl 出的 DS 都是卡常题( 首先由于此题强制在线,因此考虑分块,我们那么待查询区间 \([l,r]\) 可以很自然地被分为三个部分: 左散块 中间的整块 右散块 那么这 ...

  4. Luogu P5048 [Ynoi2019模拟赛]Yuno loves sqrt technology III 分块

    这才是真正的$N\sqrt{N}$吧$qwq$ 记录每个数$vl$出现的位置$s[vl]$,和每个数$a[i]=vl$是第几个$vl$,记为$P[i]$,然后预处理出块$[i,j]$区间的答案$f[i ...

  5. P5048 [[Ynoi2019模拟赛]Yuno loves sqrt technology III]

    为什么我感觉这题难度虚高啊-- 区间众数的出现次数- 计算器算一下 \(\sqrt 500000 = 708\) 然后我们发现这题的突破口? 考虑分块出来[L,R]块的众数出现个数 用 \(\text ...

  6. [luogu5048] [Ynoi2019模拟赛] Yuno loves sqrt technology III

    题目链接 洛谷. Solution 思路同[BZOJ2724] [Violet 6]蒲公英,只不过由于lxl过于毒瘤,我们有一些更巧妙的操作. 首先还是预处理\(f[l][r]\)表示\(l\sim ...

  7. [Ynoi2019模拟赛]Yuno loves sqrt technology III

    题目大意: 给你一个长为n的序列a,m次询问,每次查询一个区间的众数的出现次数,强制在线. 解题思路: 出题人题解 众所周知lxl是个毒瘤,Ynoi道道都是神仙题 首先得离散化. 分块后,预处理Fi, ...

  8. [Luogu5048] [Ynoi2019模拟赛]Yuno loves sqrt technology III[分块]

    题意 长为 \(n\) 的序列,询问区间众数,强制在线. \(n\leq 5\times 10^5\). 分析 考虑分块,暴力统计出整块到整块之间的众数次数. 然后答案还可能出现在两边的两个独立的块中 ...

  9. [Ynoi2019模拟赛]Yuno loves sqrt technology I

    题目描述 给你一个长为n的排列,m次询问,每次查询一个区间的逆序对数,强制在线. 题解 MD不卡了..TMD一点都卡不动. 强制在线的话也没啥好一点的方法,只能分块预处理了. 对于每个块,我们设lef ...

随机推荐

  1. python之web架构

    一.web架构简介 web.py是一个轻量级Python web框架,它简单而且功能强大.web.py是一个开源项目.该框架由已故美国作家.Reddit联合创始人.RSS规格合作创造者.著名计算机黑客 ...

  2. spl_autoload_register()函数

    一.__autoload 这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数.看下面例子: printit.class.php <?php class PRINTI ...

  3. Windows运行机理——API与SDK

    Windows运行机理这系列文章都是来至于<零基础学Qt4编程>——吴迪,个人觉得写得很好,所以搬运加以整理. 首先 API:Application Programmaing Interf ...

  4. python基础之变量和简单数据类型

    1.1 变量的命名和使用规范 变量名可以包含数字.字母.下划线,但是不能以数字开头. 变量名不能包含空格,可使用下划线来分割其中的单词. 不要将Python关键字和函数名用作变量名. 变量名应既简短又 ...

  5. Linux命令应用大词典-第35章 终端

    35.1 tty:显示当前连接到当前标准输入的终端设备文件名 35.2 consoletype:显示连接到标准输入的控制台类型 35.3 fgconsole:显示活动的虚拟终端数量 35.4 ming ...

  6. JavaWeb--------JSP语法基础学习(特别适合入门)

    准备工作: 需要Tomcat8.0,MyEclipse,JDK JSP是一种运行在服务器端的脚本语言,JSP页面又是基于HTML网页的程序,它是Java Web 开发技术的基础. 基本内容: JSP页 ...

  7. 孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9并使用pydocx模块将结果写入word文档

    孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 到今天终于完成了对docx模块针对 ...

  8. ES6 之 let / const

    本博文配合 阮一峰 <ES6 标准入门(第3版)>一书进行简要概述 ES6 中的 let 与 const. 历史遗留问题 由于 JS ES3语法中的 var 提升变量.没有块级作用域,因而 ...

  9. 二:HDFS 命令指南

    命令具体选项请参考: http://hadoop.apache.org/docs/r2.6.3/hadoop-project-dist/hadoop-hdfs/HDFSCommands.html   ...

  10. python获取指定长度的字符串

    from random import Random def random_str(randomlength=31): str = '' chars = 'abcdefghijklmnopqrstuvw ...