[BZOJ 2724] [Violet 6] 蒲公英 【分块】
题目链接:BZOJ - 2724
题目分析
这道题和 BZOJ-2821 作诗 那道题几乎是一样的,就是直接分块,每块大小 sqrt(n) ,然后将数字按照数值为第一关键字,位置为第二关键字排序,方便之后二分查找某个值在某个区间内出现的次数。
预处理出 f[i][j] 即从第 i 块到第 j 块的答案。
对于每个询问,中间的整块直接用预处理出的,两端的 sqrtn 级别的数暴力做,用二分查找它们出现的次数。
每次询问的复杂度是 sqrtn * logn 。
注意:写代码的时候又出现了给 sort 写的 Cmp() 不保证双向一致的错误!!Warning!注意代码中的 Cmp_Num() 函数,即使在不需要第二关键字的情况下,由于 Num 可能会有相同的,也必须加第二关键字以保证比较结果双向一致!
代码
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath> using namespace std; inline void Read(int &Num) {
char c; c = getchar();
while (c < '0' || c > '9') c = getchar();
Num = c - '0'; c = getchar();
while (c >= '0' && c <= '9') {
Num = Num * 10 + c - '0';
c = getchar();
}
} const int MaxN = 40000 + 5, MaxBlk = 200 + 5; int n, m, BlkSize, TotBlk;
int A[MaxN], TL[MaxN], T[MaxN], Cnt[MaxN], L[MaxBlk], R[MaxBlk], First[MaxN], Last[MaxN];
int f[MaxBlk][MaxBlk], g[MaxBlk][MaxBlk]; struct ES
{
int Pos, Num, v;
} E[MaxN]; inline bool Cmp_Num(ES e1, ES e2) {
if (e1.Num == e2.Num) return e1.Pos < e2.Pos;
return e1.Num < e2.Num;
}
inline bool Cmp_Pos(ES e1, ES e2) {return e1.Pos < e2.Pos;} int GetNum(int Num, int x, int y) {
if (x > y || x > E[Last[Num]].Pos || y < E[First[Num]].Pos) return 0;
int l, r, mid, p1, p2;
l = First[Num]; r = Last[Num];
while (l <= r) {
mid = (l + r) >> 1;
if (E[mid].Pos >= x) {
p1 = mid;
r = mid - 1;
}
else l = mid + 1;
}
l = First[Num]; r = Last[Num];
while (l <= r) {
mid = (l + r) >> 1;
if (E[mid].Pos <= y) {
p2 = mid;
l = mid + 1;
}
else r = mid - 1;
}
return p2 - p1 + 1;
} int main()
{
Read(n); Read(m);
for (int i = 1; i <= n; ++i) {
Read(E[i].Num);
E[i].Pos = i;
}
sort(E + 1, E + n + 1, Cmp_Num);
int v_Index = 0;
for (int i = 1; i <= n; ++i) {
if (i == 1 || E[i].Num > E[i - 1].Num) ++v_Index;
E[i].v = v_Index;
TL[v_Index] = E[i].Num;
}
sort(E + 1, E + n + 1, Cmp_Pos);
for (int i = 1; i <= n; ++i) A[i] = E[i].v;
sort(E + 1, E + n + 1, Cmp_Num);
for (int i = 1; i <= n; ++i) {
if (First[E[i].v] == 0) First[E[i].v] = i;
Last[E[i].v] = i;
}
BlkSize = (int)sqrt((double)n);
TotBlk = (n - 1) / BlkSize + 1;
for (int i = 1; i <= TotBlk; ++i) {
L[i] = (i - 1) * BlkSize + 1;
R[i] = i * BlkSize;
}
R[TotBlk] = n;
for (int i = 1; i <= TotBlk; ++i) {
for (int j = 1; j <= n; ++j) Cnt[j] = 0;
f[i][i - 1] = 0; g[i][i - 1] = 0;
for (int j = i; j <= TotBlk; ++j) {
f[i][j] = f[i][j - 1];
g[i][j] = g[i][j - 1];
for (int k = L[j]; k <= R[j]; ++k) {
++Cnt[A[k]];
if (Cnt[A[k]] > f[i][j] || (Cnt[A[k]] == f[i][j] && A[k] < g[i][j])) {
f[i][j] = Cnt[A[k]]; g[i][j] = A[k];
}
}
}
}
memset(Cnt, 0, sizeof(Cnt));
for (int i = 1; i <= n; ++i) T[i] = -1;
int l, r, x, y, Ct, Ans, Cu;
Ans = 0;
for (int i = 1; i <= m; ++i) {
Read(l); Read(r);
l = (l + Ans - 1) % n + 1; r = (r + Ans - 1) % n + 1;
if (l > r) swap(l, r);
x = (l - 1) / BlkSize + 1; if (l != L[x]) ++x;
y = (r - 1) / BlkSize + 1; if (r != R[y]) --y;
if (x > y) {
Ct = 0; Ans = 0;
for (int j = l; j <= r; ++j) {
++Cnt[A[j]];
if (Cnt[A[j]] > Ct || (Cnt[A[j]] == Ct && A[j] < Ans)) {
Ct = Cnt[A[j]]; Ans = A[j];
}
}
for (int j = l; j <= r; ++j) --Cnt[A[j]];
}
else {
Ct = f[x][y]; Ans = g[x][y];
for (int j = l; j < L[x]; ++j) {
++Cnt[A[j]];
if (T[A[j]] == -1) T[A[j]] = GetNum(A[j], L[x], R[y]);
Cu = Cnt[A[j]] + T[A[j]];
if (Cu > Ct || (Cu == Ct && A[j] < Ans)) {
Ct = Cu; Ans = A[j];
}
}
for (int j = r; j > R[y]; --j) {
++Cnt[A[j]];
if (T[A[j]] == -1) T[A[j]] = GetNum(A[j], L[x], R[y]);
Cu = Cnt[A[j]] + T[A[j]];
if (Cu > Ct || (Cu == Ct && A[j] < Ans)) {
Ct = Cu; Ans = A[j];
}
}
for (int j = l; j < L[x]; ++j) {--Cnt[A[j]]; T[A[j]] = -1;}
for (int j = r; j > R[y]; --j) {--Cnt[A[j]]; T[A[j]] = -1;}
}
Ans = TL[Ans];
printf("%d\n", Ans);
}
return 0;
}
[BZOJ 2724] [Violet 6] 蒲公英 【分块】的更多相关文章
- BZOJ 2724: [Violet 6]蒲公英( 分块 )
虽然AC了但是时间惨不忍睹...不科学....怎么会那么慢呢... 无修改的区间众数..分块, 预处理出Mode[i][j]表示第i块到第j块的众数, sum[i][j]表示前i块j出现次数(前缀和, ...
- BZOJ 2724: [Violet 6]蒲公英 [分块 区间众数]
传送门 题面太美不忍不放 分块分块 这种题的一个特点是只有查询,通常需要预处理:加入修改的话需要暴力重构预处理 预处理$f[i][j]$为第i块到第j块的众数,显然$f[i][j]=max{f[i][ ...
- BZOJ 2724 [Violet 6]蒲公英(分块)
题意 在线区间众数 思路 预处理出 f[i][j] 即从第 i 块到第 j 块的答案.对于每个询问,中间的整块直接用预处理出的,两端的 sqrtn 级别的数暴力做,用二分查找它们出现的次数.每次询问的 ...
- BZOJ 2724: [Violet 6]蒲公英
2724: [Violet 6]蒲公英 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1633 Solved: 563[Submit][Status ...
- BZOJ.2724.[Violet 6]蒲公英(静态分块)
题目链接 区间众数 强制在线 考虑什么样的数会成为众数 如果一个区间S1的众数为x,那么S1与新区间S2的并的众数只会是x或S2中的数 所以我们可以分块先预处理f[i][j]表示第i到第j块的众数 对 ...
- 【刷题】BZOJ 2724 [Violet 6]蒲公英
Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1 Output Sample Input ...
- 【BZOJ 2724】 2724: [Violet 6]蒲公英 (区间众数不带修改版本)
2724: [Violet 6]蒲公英 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1908 Solved: 678 Description In ...
- 【BZOJ】2724: [Violet 6]蒲公英
2724: [Violet 6]蒲公英 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 2900 Solved: 1031[Submit][Statu ...
- 【BZOJ2724】[Violet 6]蒲公英 分块+二分
[BZOJ2724][Violet 6]蒲公英 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n ...
随机推荐
- 设置U盘为第一启动顺序
本文转载:http://u.diannaodian.com/Article/1004.html 盘安装系统的首要步骤就是设置U盘为第一启动顺序.下面电脑店官网就来说说到底如何来设置U盘启动顺序吧. ...
- 如何优化cocos2d程序的内存使用和程序大小:第二部分_(转)
减少你的程序的大小 把纹理的颜色位深度减少到16位,不仅可以减少内存压力,还可以有效地减少程序的体积.但是,我们还有其它方法可以更进一步地减少程序的大小. TexturePacker PNG 图片优化 ...
- 应用层协议实现系列(一)——HTTPserver之仿nginx多进程和多路IO的实现
近期在尝试自己写一个Httpserver,在粗略研究了nginx的代码之后,决定仿照nginx中的部分设计自己实现一个高并发的HTTPserver,在这里分享给大家. 眼下使用的较多的Httpserv ...
- 转自知乎,亲民好酒推荐 分类: fool_tree的笔记本 2014-11-08 17:37 652人阅读 评论(0) 收藏
这里尽量为大家推荐一些符合大众喜好.业内公认好评."即使你不喜欢,你也会承认它不错"的酒款.而且介绍到的酒款还会有一个共同的特征,就是能让你方便的在网上买到. 大概会分为烈酒,利口 ...
- linux innode图解2
http://www.opsers.org/linux-home/base/the-knowledge-that-one-day-learn-linux-file-system.html 文件系统是操 ...
- WebLogic Server的单点登陆功能--转载
在WebLogic 8.1最新的 SP4版本中,最引人注目的要算是在安全方面,提供了用于和Microsoft Windows客户端进行Single Sign-On的Single Pass Negoti ...
- 深入分析 Java I/O 的工作机制--转载
Java 的 I/O 类库的基本架构 I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道.在当今这个数据大爆炸时代, ...
- date和long的相互转换
import java.text.SimpleDateFormat; import java.util.Date; public class T { public static void main(S ...
- 安卓工程修改包名后 Failed to find provider info for...问题
安卓工程修改包名后 Failed to find provider info for com.android...provider问题 原因: 1. 多处含包名文件须同时更改 2. Manifest里 ...
- if elsif;报错;new赋值
1. IF INSERTING THEN BEGIN 中间不能为空 END;ELSIF DELETING THEN BEGIN E ...