题目大意:有$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. Python3 linux安装

    ./configure --prefix=/usr/local/python3 --with-ssl --enable-optimizations make && make insta ...

  2. Mac安装php和redis扩展

    Mac上有特定的包管理工具homebrew,也叫brew,这里的php安装用的就是brew 1安装php brew install php@7.0. brw安装会自动管理依赖,所以不用你一个个先安装依 ...

  3. 会声会影X10x9x8最新教程

    会声会影X10x9x8最新最全教程,全部都是干货,包含素材的,下载地址:百度网盘, https://pan.baidu.com/s/1AyVS-C_VcTEz_ir70u08xQ 以下为部分内容截图: ...

  4. JSP学习(JavaBean)

    Java Web学习 一.搭建java web开发环境: (1)安装jdk (2)安装Tomcat服务器(Apache的开源项目),安装Tomcat并设置环境变量 (3)安装EclipseEE(或者M ...

  5. 征战 OSG-序及目录

    其实很早就应该写这个了,一直拖到现在就是因为懒啊. 自从七月演习回来,被划到三维平台开发部,就一直混日子,也没人带领,也没人问结果,就这么一直堕落下来了,直到有一天才发现自己也看不上自己了,觉得自己这 ...

  6. 各种对list,string操作函数的总结

    #encoding=utf-8#reverse,用来反转lista=['aa','bb','cc']a.reverse()print a#['cc', 'bb', 'aa']#不能直接print a. ...

  7. 【SpringCloud】第七篇: 高可用的分布式配置中心(Spring Cloud Config)

    前言: 必需学会SpringBoot基础知识 简介: spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选. ...

  8. 进度条加载与案例优化对比——python使用perf_count方法实现

    本章我们将讨论python3 perf_counter()的用法及它的实际应用我从中选取两个python基于rquests库的爬虫实例代码源文件进行举例 Python3 perf_counter() ...

  9. 【转】Buff机制及其实际运用

    转自 http://bbs.gameres.com/forum.php?mod=viewthread&tid=215027 首先我想说的是,这是一套机制,并不是单独的一个系统,所谓机制就是一种 ...

  10. 使用 Gradle 配置java项目

    注意点 除非调试,不要print ,否则任务不会按照依赖的顺序执行,因为我们自己喜欢调试用print,但是会打乱执行顺序. 排除测试文件: sourceSets.main.java { srcDir ...