bzoj 2724 在线区间众数
如果不是在线,就是裸的莫队。
但这道题要求在线,然后就不会了。。
标程:
http://hi.baidu.com/__vani/item/ecc63f3527395283c2cf2945
算法主要是分块,然后处理处f[i][j]从第i块到第j块这个块区间的信息。
第一个算法的思想是每个块区间除了维护答案,还记录了该块区间中每个数的个数,这样可以快速添加增加一个数到该区间,所以他查询的时候就是找到查询区间的完整的块,然后向左右扩展,记录下答案,再撤销修改。设块的长度为L,则时间复杂度为:O(m*n+n*n*n/L/L),L=n1/3时最小。
第二个算法不需要记下每个块区间中每个数出现次数,只记下众数及出现次数,查询时,因为可能的答案是查询区间包含的块区间的众数以及两端不在块区间的数,至于两边的数,可以枚举判断它是否可能是众数。O(m*n0.5*logn)
算法一:
/**************************************************************
Problem: 2724
User: idy002
Language: C++
Result: Accepted
Time:7156 ms
Memory:251984 kb
****************************************************************/ #include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#define maxn 40010
#define maxs 40
using namespace std; struct Cnt {
int cnt[maxn], mw;
inline void operator +=( int w ) {
cnt[w]++;
update(w);
}
inline void update( int w ) {
if( cnt[w]>cnt[mw] || (cnt[w]==cnt[mw] && w<mw) )
mw = w;
}
}; int n, m;
int w[maxn];
int lx[maxs], rx[maxs], mccno[maxn], stot;
int disc[maxn], md;
Cnt f[maxs][maxs], cur; void partition() {
int len = (int)pow(n,2.0/3.0)+;
stot = n/len+(n%len!=);
rx[] = ;
for( int i=; i<=stot; i++ )
rx[i]=rx[i-]+len, lx[i]=rx[i-]+;
rx[stot] = min( rx[stot], n );
for( int i=; i<=stot; i++ )
for( int j=lx[i]; j<=rx[i]; j++ )
mccno[j] = i;
}
void discard() {
for( int i=; i<=n; i++ )
disc[i] = w[i];
sort( disc+, disc++n );
md = unique( disc+, disc++n ) - disc - ;
for( int i=; i<=n; i++ )
w[i] = lower_bound( disc+, disc++md, w[i] ) - disc;
}
void prep() {
for( int i=; i<=stot; i++ )
for( int j=lx[i]; j<=rx[i]; j++ ) {
f[i][i].cnt[w[j]]++;
f[i][i].update(w[j]);
}
for( int i=; i<=stot; i++ ) {
for( int j=i+; j<=stot; j++ ) {
for( int k=; k<=md; k++ )
f[i][j].cnt[k] = f[i][j-].cnt[k]+f[j][j].cnt[k];
f[i][j].cnt[] = ;
f[i][j].mw = ;
for( int k=; k<=md; k++ )
f[i][j].update(k);
}
}
}
int query( int l, int r ) {
int rt;
int sl=mccno[l], sr=mccno[r];
if( sl==sr ) {
for( int j=l; j<=r; j++ ) {
cur.cnt[w[j]]++;
cur.update( w[j] );
}
rt = cur.mw;
cur.mw = ;
for( int j=l; j<=r; j++ )
cur.cnt[w[j]]--;
return rt;
}
int ml = mccno[l], mr = mccno[r];
if( mccno[l]==mccno[l-] ) ml++;
if( mccno[r]==mccno[r+] ) mr--;
Cnt &cur = f[ml][mr];
int oldw = cur.mw;
for( int j=l; j<lx[ml]; j++ ) cur += w[j];
for( int j=rx[mr]+; j<=r; j++ ) cur += w[j];
rt = cur.mw;
for( int j=l; j<lx[ml]; j++ ) cur.cnt[w[j]]--;
for( int j=rx[mr]+; j<=r; j++ ) cur.cnt[w[j]]--;
cur.mw = oldw;
return rt;
}
int main() {
scanf( "%d%d", &n, &m );
for( int i=; i<=n; i++ )
scanf( "%d", w+i ); discard();
partition();
prep(); int x = ;
for( int i=,l,r; i<=m; i++ ) {
scanf( "%d%d", &l, &r );
l = ( l+x- )%n+;
r = ( r+x- )%n+;
if( r<l ) swap(l,r);
printf( "%d\n", x=disc[query(l,r)] );
}
}
算法二:
/**************************************************************
Problem: 2724
User: idy002
Language: C++
Result: Accepted
Time:17888 ms
Memory:2416 kb
****************************************************************/ #include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define maxn 40010
#define maxs 210
using namespace std; int n, m;
int a[maxn];
int lx[maxs], rx[maxs], mno[maxn], stot;
int fa[maxs][maxs], fn[maxs][maxs];
int cnt[maxn], cura, curn;
int dl[maxn], dr[maxn], disc[maxn], md; struct Pair {
int w, pos;
Pair(){}
Pair( int w, int pos ):w(w),pos(pos){}
};
Pair vod[maxn];
bool cmpwp( const Pair & a, const Pair & b ) {
return a.w<b.w || (a.w==b.w&&a.pos<b.pos);
}
bool cmpp( const Pair & a, const Pair & b ) {
return a.pos<b.pos;
} void part() {
int len = (int)sqrt(n)+;
stot = n/len+(n%len!=);
for( int i=; i<=stot; i++ ) {
lx[i] = rx[i-]+;
rx[i] = rx[i-]+len;
if( i==stot ) rx[i]=n;
for( int j=lx[i]; j<=rx[i]; j++ )
mno[j] = i;
}
}
void discard() {
for( int i=; i<=n; i++ )
disc[i] = a[i];
sort( disc+, disc++n );
md = unique( disc+, disc++n ) - disc - ;
for( int i=; i<=n; i++ ) {
a[i] = lower_bound( disc+, disc++md, a[i] ) - disc;
vod[i] = Pair( a[i], i );
}
sort( vod+, vod++n, cmpwp );
for( int i=; i<=n; i++ ) {
if( vod[i].w!=vod[i-].w ) {
dl[vod[i].w] = i;
dr[vod[i-].w] = i-;
}
}
dr[vod[n].w] = n;
}
int qu_cnt( int w, int l, int r ) {
return upper_bound(vod+dl[w],vod+dr[w]+,Pair(w,r),cmpp)
- lower_bound(vod+dl[w],vod+dr[w]+,Pair(w,l),cmpp);
}
void prep() {
for( int i=; i<=stot; i++ ) {
memset( cnt, , sizeof(cnt) );
for( int j=i; j<=stot; j++ ) {
for( int k=lx[j]; k<=rx[j]; k++ ) {
cnt[a[k]]++;
if( cnt[a[k]]>cnt[cura] || (cnt[a[k]]==cnt[cura] && a[k]<cura) )
cura = a[k];
}
fa[i][j] = cura;
fn[i][j] = cnt[cura];
}
}
}
void update( int w, int l, int r ) {
int c = qu_cnt( w, l, r );
if( c>curn || (c==curn && w<cura) ) {
cura = w;
curn = c;
}
}
int query( int l, int r ) {
int ml = mno[l], mr = mno[r];
if( ml==mr ) {
cura = a[l];
curn = qu_cnt( a[l], l, r );
for( int j=l+; j<=r; j++ )
update(a[j],l,r);
return cura;
}
if( mno[l]==mno[l-] ) ml++;
if( mno[r]==mno[r+] ) mr--;
if( ml>mr ) {
cura = a[l];
curn = qu_cnt( a[l], l, r );
} else {
cura = fa[ml][mr];
curn = fn[ml][mr];
}
for( int j=l; j<lx[ml]; j++ )
update(a[j],l,r);
for( int j=r; j>rx[mr]; j-- )
update(a[j],l,r);
return cura;
} int main() {
scanf( "%d%d", &n, &m );
for( int i=; i<=n; i++ )
scanf( "%d", a+i ); part();
discard();
prep(); for( int i=,x=,l,r; i<=m; i++ ) {
scanf( "%d%d", &l, &r );
l = (l+x-)%n+;
r = (r+x-)%n+;
if( l>r ) swap(l,r);
printf( "%d\n", x=disc[query(l,r)] );
}
}
bzoj 2724 在线区间众数的更多相关文章
- BZOJ 2724 [Violet 6]蒲公英(分块)
题意 在线区间众数 思路 预处理出 f[i][j] 即从第 i 块到第 j 块的答案.对于每个询问,中间的整块直接用预处理出的,两端的 sqrtn 级别的数暴力做,用二分查找它们出现的次数.每次询问的 ...
- 【BZOJ 2724】 2724: [Violet 6]蒲公英 (区间众数不带修改版本)
2724: [Violet 6]蒲公英 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1908 Solved: 678 Description In ...
- 【BZOJ 2724】 蒲公英
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2724 [算法] 分块算法在线维护区间众数 分块算法的精髓就在于 : 大段维护,局部朴 ...
- [BZOJ 2724] [Violet 6] 蒲公英 【分块】
题目链接:BZOJ - 2724 题目分析 这道题和 BZOJ-2821 作诗 那道题几乎是一样的,就是直接分块,每块大小 sqrt(n) ,然后将数字按照数值为第一关键字,位置为第二关键字排序,方便 ...
- BZOJ 2724: [Violet 6]蒲公英( 分块 )
虽然AC了但是时间惨不忍睹...不科学....怎么会那么慢呢... 无修改的区间众数..分块, 预处理出Mode[i][j]表示第i块到第j块的众数, sum[i][j]表示前i块j出现次数(前缀和, ...
- BZOJ.2724.[Violet 6]蒲公英(静态分块)
题目链接 区间众数 强制在线 考虑什么样的数会成为众数 如果一个区间S1的众数为x,那么S1与新区间S2的并的众数只会是x或S2中的数 所以我们可以分块先预处理f[i][j]表示第i到第j块的众数 对 ...
- BZOJ 2724 蒲公英 | 分块模板题
题意 给出一个序列,在线询问区间众数.如果众数有多个,输出最小的那个. 题解 这是一道分块模板题. 一个询问的区间的众数,可能是中间"整块"区间的众数,也可能是左右两侧零散的数中的 ...
- 洛谷P4168 蒲公英 分块处理区间众数模板
题面. 许久以前我还不怎么去机房的时候,一位大佬好像一直在做这道题,他称这道题目为"大分块". 其实这道题目的思想不只可以用于处理区间众数,还可以处理很多区间数值相关问题. 让我们 ...
- 蒲公英(bzoj2724)(分块+区间众数)
Input Output Sample Input 6 3 1 2 3 2 1 2 1 5 3 6 1 5 Sample Output 1 2 1 HINT \(n <= 40000\),$ m ...
随机推荐
- F - Debate CodeForces - 1070F 思维
题目链接:https://vjudge.net/problem/CodeForces-1070F 具体思路:首先把所有的00放进去,然后对于10 和01 的取两个数目最小值t,排完序后将前t个加起来, ...
- Fiddler -工具使用介绍(附:拦截请求并修改返回数据)(转)
一.Fiddler 介绍 Fiddler 是一个使用 C# 编写的 http 抓包工具.它使用灵活,功能强大,支持众多的 http 调试任务,是 web.移动应用的开发调试利器. 1,功能特点 同 H ...
- jsoup抓取网页报错UnsupportedMimeTypeException
今天在用Jsoup爬虫的时候两次遇到下面错误 Exception in thread "main" org.jsoup.UnsupportedMimeTypeException: ...
- python基础===数据伪造模块faker
介绍文档: https://pypi.org/project/Faker/ https://faker.readthedocs.io/en/latest/ https://faker.readthed ...
- Mysql存储之ORM框架SQLAlchemy(一)
上一篇我们说了mysql存储的原生语句方式,因为原生语句每次写都比较的复杂,所以这里我们说一种引用实体类的方式来操作数据库. 什么是ORM ORM技术:Object-Relational Mappin ...
- 008 BlockingQueue理解
原文https://www.cnblogs.com/WangHaiMing/p/8798709.html 本篇将详细介绍BlockingQueue,以下是涉及的主要内容: BlockingQueue的 ...
- Python os模块和sys模块 操作系统的各种接口
一.os模块 这个模块提供了一个便携式去使用操作系统的相关功能,如果只是想操作路径,请参阅os.path模块. ''' os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 ...
- 通过复制(拷贝)新建javaweb项目报错无法访问
我们有时候为了方便,用eclipse在原来动态web项目上直接复制,粘贴项目,来形成以一个新的项目.可是运行的时候,它显示的url地址,还是原来的项目地址.初步判定,有可能是eclipse配置的问题. ...
- 双系统卸载linux和装双系统的方法
卸载linux系统: 因为本人装的是windows和Ubuntu,所以引导程序在linux系统里,linux系统可以引导windows系统,而Windows不能引导linux,所以需要修改引导程序,使 ...
- Vim文本编辑命令
Vim Vim是一个类似于Vi的著名的功能强大.高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性.[1] VIM是自由软件. Vim普遍被推崇为类Vi编辑器中最好的一个,事实上真正的劲敌来 ...