Luogu P4168 [Violet]蒲公英(Loj 分块模板9)
[Violet]蒲公英
题目背景
亲爱的哥哥:
你在那个城市里面过得好吗?
我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……
最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!
哥哥你要快点回来哦!
爱你的妹妹 Violet
Azure 读完这封信之后微笑了一下。
“蒲公英吗……”
题目描述
在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。
为了简化起见,我们把所有的蒲公英看成一个长度为
而每次询问一个区间
注意,你的算法必须是在线的。
输入格式
第一行有两个整数,分别表示蒲公英的数量
第二行有
接下来
令上次询问的结果为
最终的询问区间为计算后的
输出格式
对于每次询问,输出一行一个整数表示答案。
样例 #1
样例输入 #1
6 3 1 2 3 2 1 2 1 5 3 6 1 5
样例输出 #1
1 2 1
提示
数据规模与约定
- 对于
的数据,保证 。 - 对于
的数据,保证 , , , 。
#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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具