Luogu P4168 [Violet]蒲公英(Loj 分块模板9)

[Violet]蒲公英

题目背景

亲爱的哥哥:

你在那个城市里面过得好吗?

我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……

最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!

哥哥你要快点回来哦!

爱你的妹妹 Violet

Azure 读完这封信之后微笑了一下。

“蒲公英吗……”

题目描述

在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。

为了简化起见,我们把所有的蒲公英看成一个长度为 n 的序列 {a1,a2..an},其中 ai 为一个正整数,表示第 i 棵蒲公英的种类编号。

而每次询问一个区间 [l,r],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。

注意,你的算法必须是在线的

输入格式

第一行有两个整数,分别表示蒲公英的数量 n 和询问次数 m

第二行有 n 个整数,第 i 个整数表示第 i 棵蒲公英的种类 ai

接下来 m 行,每行两个整数 l0,r0,表示一次询问。输入是加密的,解密方法如下:

令上次询问的结果为 x(如果这是第一次询问,则 x=0),设 l=((l0+x1)modn)+1,r=((r0+x1)modn)+1。如果 l>r,则交换 l,r
最终的询问区间为计算后的 [l,r]

输出格式

对于每次询问,输出一行一个整数表示答案。

样例 #1

样例输入 #1

6 3
1 2 3 2 1 2
1 5
3 6
1 5

样例输出 #1

1
2
1

提示

数据规模与约定

  • 对于 20% 的数据,保证 n,m3000
  • 对于 100% 的数据,保证 1n400001m500001ai1091l0,r0n
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int n, m, block, cnt, ans, l, r;//block是块的长度,cnt是块的个数,ans是上一次询问的答案
int a[5211314], b[5211314], len;
int mode[521][1314], s[521][131400], pos[5211314];
//mode[i][j]表示从i到j的块中的众数,s[i][j]表示前i个块中出现j的次数
int barrel[5211314];
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch - '0');
ch = getchar();
}
return x * f;
}
void print(int x) {
if (x < 0) x *= -1, putchar('-');
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
return;
}
void write(int x) {
print(x);
putchar('\n');
return;
}
inline void Pretreatment() {
sort(b + 1, b + 1 + n);
len = unique(b + 1, b + 1 + n) - (b + 1);
for (int i = 1; i <= n; ++ i) {
a[i] = lower_bound(b + 1, b + 1 + len, a[i]) - b;
}
for (int i = 1; i <= cnt; ++ i) {
for (int j = (i - 1) * block + 1; j <= min(i * block, n); ++ j) {
//注意是j <= min(i * block, n)
s[i][a[j]] ++;
}
for (int j = 1; j <= len; ++ j) {
s[i][j] += s[i - 1][j];
}
}
int maxn;
for (int i = 1; i <= cnt; ++ i) {
for (int j = i; j <= cnt; ++ j) {
maxn = mode[i][j - 1];
for (int k = (j - 1) * block + 1; k <= min(j * block, n); ++ k) {
if ((s[j][a[k]] - s[i - 1][a[k]] > s[j][maxn] - s[i - 1][maxn]) ||
(s[j][a[k]] - s[i - 1][a[k]] == s[j][maxn] - s[i - 1][maxn] && a[k] < maxn)) {
maxn = a[k];
}
}
mode[i][j] = maxn;
}
}
}
int main() {
n = read(), m = read();
block = sqrt(n);
for (int i = 1; i <= n; ++ i) {
a[i] = b[i] = read();
pos[i] = (i - 1) / block + 1;
if (pos[i] != pos[i - 1]) cnt ++;
}
Pretreatment();
for (int temp = 1; temp <= m; ++ temp) {
int Mode = 0;
l = read();
r = read();
l = ((l + ans - 1) % n) + 1;
r = ((r + ans - 1) % n) + 1;
if (l > r) swap(l, r);
if (pos[r] - pos[l] <= 1) {
for (int i = l; i <= r; ++ i) barrel[a[i]] ++;
for (int i = l; i <= r; ++ i) {
if ((barrel[a[i]] > barrel[Mode]) ||
(barrel[a[i]] == barrel[Mode] && a[i] < Mode)) {
Mode = a[i];
}
//barrel[a[i]] = 0;
//这里barrel[a[i]]=0不能写里面,不然barrel[Mode]为0,下面同理
}
for (int i = l; i <= r; ++ i) barrel[a[i]] = 0;
}
else {
for (int i = l; i <= block * pos[l]; ++ i) {
barrel[a[i]] ++;
}
for (int i = (pos[r] - 1) * block + 1; i <= r; ++ i) {
barrel[a[i]] ++;
}
Mode = mode[pos[l] + 1][pos[r] - 1];
for (int i = l, pre, now; i <= block * pos[l]; ++ i) {
pre = barrel[a[i]] + (s[pos[r] - 1][a[i]] - s[pos[l]][a[i]]);
//barrel[i]是两端不完全覆盖的块中a[i]出现的次数
//s[pos[r] - 1][a[i]] - s[pos[l]][a[i]]则是完全覆盖的块中a[i]出现的次数
now = barrel[Mode] + (s[pos[r] - 1][Mode] - s[pos[l]][Mode]);
if ((pre > now) || (pre == now && a[i] < Mode)) Mode = a[i];
//barrel[a[i]] = 0;
}
for (int i = (pos[r] - 1) * block + 1, pre, now; i <= r; ++ i) {
pre = barrel[a[i]] + (s[pos[r] - 1][a[i]] - s[pos[l]][a[i]]);
now = barrel[Mode] + (s[pos[r] - 1][Mode] - s[pos[l]][Mode]);
if ((pre > now) || (pre == now && a[i] < Mode)) Mode = a[i];
//barrel[a[i]] = 0;
}
for (int i = l, pre, now; i <= block * pos[l]; ++ i) barrel[a[i]] = 0;
for (int i = (pos[r] - 1) * block + 1, pre, now; i <= r; ++ i) barrel[a[i]] = 0;
}
ans = b[Mode];
write(ans);
}
return 0;
}
posted @   觉清风  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示