[BZOJ2724][Violet 6]蒲公英
[BZOJ2724][Violet 6]蒲公英
试题描述
.gif)
输入
修正一下
l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1
输出
.gif)
输入示例
6 3 1 2 3 2 1 2 1 5 3 6 1 5
输出示例
1 2 1
数据规模及约定
修正下:
n <= 40000, m <= 50000
题解
分块,先预处理出 f[i][j] 表示第 i 块到第 j 块的众数,枚举起点 i 然后扫一遍就好了。
其次是询问,对于一个询问 [ql, qr],其中 ql 属于块 l,qr 属于块 r,众数要么是 f[l+1][r-1],要么是不完整块中的数,所以我们需要搞一个 calc(l, r, x) 功能,表示询问 [l, r] 中 x 出现的次数,有了这个功能后就可以做到把答案初始设为 f[l+1][r-1](O(1)),然后 O(sqrt(n)) 暴力枚举不完整块中的数,如果出现次数比当前的多,就更新答案。
这个 calc() 函数可以这样搞:把所有数离散,每个数的位置记下来,然后当询问 calc(l, r, x) 在 x 的位置序列上二分一下就可以计算了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <vector> using namespace std; const int BufferSize = 1 << 16; char buffer[BufferSize], *Head, *Tail; inline char Getchar() { if (Head == Tail) { int l = fread(buffer, 1, BufferSize, stdin); Tail = (Head = buffer) + l; } return *Head++; } int read() { int x = 0, f = 1; char c = Getchar(); while (!isdigit(c)){ if (c == '-' ) f = -1; c = Getchar(); } while (isdigit(c)){ x = x * 10 + c - '0' ; c = Getchar(); } return x * f; } #define maxn 40010 #define maxq 210 int n, m, num[maxn], A[maxn], st[maxq], en[maxq], bl[maxn], cntb, f[maxq][maxq], cntn[maxn]; vector < int > pos[maxn]; int calc( int l, int r, int x) { return upper_bound(pos[x].begin(), pos[x].end(), r) - lower_bound(pos[x].begin(), pos[x].end(), l); } int query( int ql, int qr) { int l = bl[ql], r = bl[qr]; if (r - l <= 1) { int ans = A[ql], mx = calc(ql, qr, ans); for ( int i = ql + 1; i <= qr; i++) { int tmp = calc(ql, qr, A[i]); if (mx < tmp || (mx == tmp && ans > A[i])) ans = A[i], mx = tmp; } return ans; } int ans = f[l+1][r-1], mx = calc(ql, qr, ans); for ( int i = ql; i <= en[l]; i++) { int tmp = calc(ql, qr, A[i]); if (mx < tmp || (mx == tmp && ans > A[i])) ans = A[i], mx = tmp; } for ( int i = st[r]; i <= qr; i++) { int tmp = calc(ql, qr, A[i]); if (mx < tmp || (mx == tmp && ans > A[i])) ans = A[i], mx = tmp; } return ans; } int main() { n = read(); m = read(); int siz = ( int )sqrt(n + .5); for ( int i = 1; i <= n; i++) { num[i] = A[i] = read(); int p = (i - 1) / siz + 1; cntb = p; if (!st[p]) st[p] = i; en[p] = i; bl[i] = p; } sort(num + 1, num + n + 1); for ( int i = 1; i <= n; i++) A[i] = lower_bound(num + 1, num + n + 1, A[i]) - num; for ( int i = 1; i <= cntb; i++) { memset(cntn, 0, sizeof (cntn)); for ( int j = st[i]; j <= n; j++) { cntn[A[j]]++; int r = bl[j]; if (r > i && !f[i][r]) f[i][r] = f[i][r-1]; if (!f[i][r] || cntn[f[i][r]] < cntn[A[j]] || (cntn[f[i][r]] == cntn[A[j]] && f[i][r] > A[j])) f[i][r] = A[j]; } } for ( int i = 1; i <= n; i++) pos[A[i]].push_back(i); int x = 0; while (m--) { int l = (read() + x - 1) % n + 1, r = (read() + x - 1) % n + 1; if (l > r) swap(l, r); int tmp = query(l, r); printf( "%d\n" , num[tmp]); x = num[tmp]; } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析