[BZOJ2724][Violet 6]蒲公英

试题描述

输入

修正一下

l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 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 的位置序列上二分一下就可以计算了。

#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;
}

[BZOJ2724][Violet 6]蒲公英的更多相关文章

  1. BZOJ2724 [Violet 6]蒲公英 分块

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2724.html 题目传送门 - BZOJ2724 题意 求区间最小众数,强制在线. $n$ 个数,$m ...

  2. bzoj2724: [Violet 6]蒲公英(离散化+分块)

    我好弱啊..这题调了2天QwQ 题目大意:给定一个长度为n(n<=40000)的序列,m(m<=50000)次询问l~r之间出现次数最多的数.(区间众数) 这题如果用主席树就可以不用处理一 ...

  3. bzoj2724: [Violet 6]蒲公英 分块 区间众数 论algorithm与vector的正确打开方式

    这个,要处理各个数的话得先离散,我用的桶. 我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数. 证明:若不是这里的数连区间的众 ...

  4. 【分块】bzoj2724 [Violet 6]蒲公英

    分块,离散化,预处理出: ①前i块中x出现的次数(差分): ②第i块到第j块中的众数是谁,出现了多少次. 询问的时候,对于整块的部分直接获得答案:对于零散的部分,暴力统计每个数出现的次数,加上差分的结 ...

  5. bzoj2724: [Violet 6]蒲公英(分块)

    传送门 md调了一个晚上最后发现竟然是空间开小了……明明算出来够的…… 讲真其实我以前不太瞧得起分块,觉得这种基于暴力的数据结构一点美感都没有.然而今天做了这道分块的题才发现分块的暴力之美(如果我空间 ...

  6. 【BZOJ2724】[Violet 6]蒲公英 分块+二分

    [BZOJ2724][Violet 6]蒲公英 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n ...

  7. BZOJ 2724: [Violet 6]蒲公英

    2724: [Violet 6]蒲公英 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1633  Solved: 563[Submit][Status ...

  8. BZOJ 2724: [Violet 6]蒲公英( 分块 )

    虽然AC了但是时间惨不忍睹...不科学....怎么会那么慢呢... 无修改的区间众数..分块, 预处理出Mode[i][j]表示第i块到第j块的众数, sum[i][j]表示前i块j出现次数(前缀和, ...

  9. BZOJ_2724_[Violet 6]蒲公英_分块

    BZOJ_2724_[Violet 6]蒲公英_分块 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod ...

随机推荐

  1. 在线富文本编辑器FckEditor配置(.Net Framework 3.5)

    进入FCKeditor文件夹,编辑 fckconfig.js 文件.1.上传设置  .  var _FileBrowserLanguage         = 'php' ;         // a ...

  2. 《TCP/IP详解卷1:协议》第19章 TCP的交互数据流-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  3. C#基础知识系列四(运算符汇总)

    前言  本节主要来讲C#中的各种运算符.主要包括is运算符.as运算符.checked和unchecked运算符.sizeof运算符.空接合运算符(??).&和&&.移位运算符 ...

  4. angular实例教程(用来熟悉指令和过滤器的编写)

    angular的插件太少了,  所以很多指令和过滤器都要自己写,  所以对指令传进来的参数, 以及angular编译的流程更加熟悉才行写出好的插件, 有些简单的指令是参考angularUI里面, 作为 ...

  5. 表单脚本api_contenteditable

    <html> <head></head> <body> <form> <div contenteditable>ssadas&l ...

  6. Java基础-String、StringBuffer、StringBuilder

    看下面这段代码: public class Main { public static void main(String[] args) { String string = ""; ...

  7. 【CodeForces 577B】Modulo Sum

    题 题意 给你n(1 ≤ n ≤ 106)个数a1..an(0 ≤ ai ≤ 109),再给你m( 2 ≤ m ≤ 103)如果n个数的子集的和可以被m整除,则输出YES,否则NO. 分析 分两种情况 ...

  8. 【POJ 1035】Spell checker

    题 题意 每个单词,如果字典里存在,输出”该单词 is correct“:如果字典里不存在,但是可以通过删除.添加.替换一个字母得到字典里存在的单词,那就输出“该单词:修正的单词”,并按字典里的顺序输 ...

  9. tuple内部方法

    代码: #tuple内部方法 ac=('a','r','6','d','a','b','b','e') print(dir(ac)) print(ac.count('a')) print(ac.ind ...

  10. Hibernate中一级缓存和二级缓存使用详解

    一.一级缓存二级缓存的概念解释 (1)一级缓存就是Session级别的缓存,一个Session做了一个查询操作,它会把这个操作的结果放在一级缓存中,如果短时间内这个 session(一定要同一个ses ...