[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 ...
随机推荐
- 解决方法:未能加载文件或程序集“Microsoft.Office.Interop.Excel。。
.NET错误提示:未能加载文件或程序集“Microsoft.Office.Interop.Excel, Version=11.0.0.0, Culture=neutral, PublicKeyToke ...
- Java keyword具体解释
訪问控制修饰符号 1) private 私有的 private keyword是訪问控制修饰符,能够应用于类.方法或字段(在类中声明的变量). 仅仅能在声明 private(内部)类.方 ...
- java中经常使用的日期格式化(全)
import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; imp ...
- Charles --- Mac 抓包工具
安装 官方网站Charles 是一款收费软件,可以免费体验30天.网上有破解版. 使用 infoq 上有一篇很棒的教程:iOS开发工具——网络封包分析工具Charles 注意事项 这是我使用过程中遇到 ...
- Java 国际化 语言切换
Java国际化 我们使用java.lang.Locale来构造Java国际化的情境. java.lang.Locale代表特定的地理.政治和文化.需要Locale来执行其任务的操作叫语言环境敏感的 ...
- 根据引用jar包路径查找原JAR包
网站:http://www.findjar.com/. 就是这个网站,经常在网上看到一些好的源码,什么都说了,就是没有说明需要引入那个包,这个包需要从什么地方下载,有些时候在网上搜索还不一定搜索得到, ...
- 10.31 morning
NP(np)Time Limit:1000ms Memory Limit:64MB题目描述LYK 喜欢研究一些比较困难的问题,比如 np 问题.这次它又遇到一个棘手的 np 问题.问题是这个样子的:有 ...
- C#快速排序法
最近面试的时候,被问到了快速排序法.一时之间,无法想起算法来. 重新看了书本,算法如下: 1)设置两个变量I.J,排序开始的时候:I=0,J=N-1: 2)以第一个数组元素作为关键数据,赋值给key, ...
- swift把汉字转换为拼音,并且截取首字母做索引用
var transformContents = CFStringCreateMutableCopy(nil, 0, "咋啊的看到回复阿斯顿发货发哦iasdifas")CFStrin ...
- javascript基础学习(五)
javascript之函数 学习要点: 函数的介绍 函数的参数 函数的属性和方法 系统函数 一.函数的介绍 1.函数就是一段javascript代码.可以分为用户自定义函数和系统函数. 如果一个函 ...