[BZOJ2724][Violet 6]蒲公英
[BZOJ2724][Violet 6]蒲公英
试题描述
.gif)
输入
.gif)
修正一下
l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1
输出
.gif)
输入示例
输出示例
数据规模及约定
.gif)
修正下:
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]蒲公英的更多相关文章
- BZOJ2724 [Violet 6]蒲公英 分块
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2724.html 题目传送门 - BZOJ2724 题意 求区间最小众数,强制在线. $n$ 个数,$m ...
- bzoj2724: [Violet 6]蒲公英(离散化+分块)
我好弱啊..这题调了2天QwQ 题目大意:给定一个长度为n(n<=40000)的序列,m(m<=50000)次询问l~r之间出现次数最多的数.(区间众数) 这题如果用主席树就可以不用处理一 ...
- bzoj2724: [Violet 6]蒲公英 分块 区间众数 论algorithm与vector的正确打开方式
这个,要处理各个数的话得先离散,我用的桶. 我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数. 证明:若不是这里的数连区间的众 ...
- 【分块】bzoj2724 [Violet 6]蒲公英
分块,离散化,预处理出: ①前i块中x出现的次数(差分): ②第i块到第j块中的众数是谁,出现了多少次. 询问的时候,对于整块的部分直接获得答案:对于零散的部分,暴力统计每个数出现的次数,加上差分的结 ...
- bzoj2724: [Violet 6]蒲公英(分块)
传送门 md调了一个晚上最后发现竟然是空间开小了……明明算出来够的…… 讲真其实我以前不太瞧得起分块,觉得这种基于暴力的数据结构一点美感都没有.然而今天做了这道分块的题才发现分块的暴力之美(如果我空间 ...
- 【BZOJ2724】[Violet 6]蒲公英 分块+二分
[BZOJ2724][Violet 6]蒲公英 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n ...
- BZOJ 2724: [Violet 6]蒲公英
2724: [Violet 6]蒲公英 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1633 Solved: 563[Submit][Status ...
- BZOJ 2724: [Violet 6]蒲公英( 分块 )
虽然AC了但是时间惨不忍睹...不科学....怎么会那么慢呢... 无修改的区间众数..分块, 预处理出Mode[i][j]表示第i块到第j块的众数, sum[i][j]表示前i块j出现次数(前缀和, ...
- BZOJ_2724_[Violet 6]蒲公英_分块
BZOJ_2724_[Violet 6]蒲公英_分块 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod ...
随机推荐
- Bootstrap3.0学习第二十轮(JavaScript插件——滚动监听)
详情请查看 http://aehyok.com/Blog/Detail/26.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:h ...
- Javascript基础系列之(七)函数(定义和调运函数)
函数是一个可以随时运行的语句,简单说,函数是完成某个功能的一组语句,它接受0或者多个参数. 函数的基本语法如下 function functionName([arg0,arg1,......argN] ...
- 在CentOS上装 ElasticSearch
参考官方文档:Install Elasticsearch with RPM ElasticSearch依赖Java,所以需要先安装Java: 到Oracle官网找到下载链接 http://www.or ...
- JS模式:又一个简单的工厂模式
<!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...
- Java基础-四要素之一《封装》
封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保 ...
- Fedora和Ubuntu下安装OpenGL开发环境配置
Fedora下OpenGl开发环境配置 开发OpenGL工程需要3个库文件和对应的头文件: libglut.so,libGLU.so,libGL.so, gl.h ,glu.h, glut.h 这些库 ...
- BZOJ1968 [Ahoi2005]COMMON 约数研究
Description Input 只有一行一个整数 N(0 < N < 1000000). Output 只有一行输出,为整数M,即f(1)到f(N)的累加和. Sample Input ...
- POJ1845Sumdiv(求所有因子和 + 唯一分解定理)
Sumdiv Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 17387 Accepted: 4374 Descripti ...
- java对象存储管理
java程序在内存中的存储分配情况: 堆区: 1.存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的目的是得到操作指令) 2.jvm只有一个堆区(heap)被所有线程共享, ...
- Linux VPS新硬盘分区与挂载教程
通过fdisk -l我们可以看到/dev/xvdb(此名称因系统而异)容量有23.6G,而且没有分区,接下来我们对它进行分区和挂载 (红色字为需要输入的部分,黑色字为系统显示部分) 1.fdisk - ...