如果不是在线,就是裸的莫队。

但这道题要求在线,然后就不会了。。

标程:

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 在线区间众数的更多相关文章

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

    题意 在线区间众数 思路 预处理出 f[i][j] 即从第 i 块到第 j 块的答案.对于每个询问,中间的整块直接用预处理出的,两端的 sqrtn 级别的数暴力做,用二分查找它们出现的次数.每次询问的 ...

  2. 【BZOJ 2724】 2724: [Violet 6]蒲公英 (区间众数不带修改版本)

    2724: [Violet 6]蒲公英 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1908  Solved: 678 Description In ...

  3. 【BZOJ 2724】 蒲公英

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2724 [算法] 分块算法在线维护区间众数 分块算法的精髓就在于 : 大段维护,局部朴 ...

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

    题目链接:BZOJ - 2724 题目分析 这道题和 BZOJ-2821 作诗 那道题几乎是一样的,就是直接分块,每块大小 sqrt(n) ,然后将数字按照数值为第一关键字,位置为第二关键字排序,方便 ...

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

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

  6. BZOJ.2724.[Violet 6]蒲公英(静态分块)

    题目链接 区间众数 强制在线 考虑什么样的数会成为众数 如果一个区间S1的众数为x,那么S1与新区间S2的并的众数只会是x或S2中的数 所以我们可以分块先预处理f[i][j]表示第i到第j块的众数 对 ...

  7. BZOJ 2724 蒲公英 | 分块模板题

    题意 给出一个序列,在线询问区间众数.如果众数有多个,输出最小的那个. 题解 这是一道分块模板题. 一个询问的区间的众数,可能是中间"整块"区间的众数,也可能是左右两侧零散的数中的 ...

  8. 洛谷P4168 蒲公英 分块处理区间众数模板

    题面. 许久以前我还不怎么去机房的时候,一位大佬好像一直在做这道题,他称这道题目为"大分块". 其实这道题目的思想不只可以用于处理区间众数,还可以处理很多区间数值相关问题. 让我们 ...

  9. 蒲公英(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 ...

随机推荐

  1. Lithium中关键特性更新

    Lithium中关键特性更新 1. Lithium特性更新概述 Lithium相对于Helium更新特性共27项,其中原有特性提升或增强13项,新增特性14项,如下表所示 特性类型 相对于Helium ...

  2. Android稳定性测试工具Monkey的使用

    综述    Monkey是一个命令行工具,它可以运行在我们的模拟器或者设备当中.它可以发送一些伪随机的用户事件流,例如点击.触摸.手势等.我们能够使用Monkey工具来对我们所开发的应用进行压力测试. ...

  3. 商城项目(ssm+dubbo+nginx+mysql统合项目)总结(2)

    我不会在这里贴代码和详细步骤什么的,我觉得就算我把它贴出来,你们照着步骤做还是会出很多问题,我推荐你们去看一下黑马的这个视频,我个人感觉很不错,一步一步走下来可以学到很多东西.另外,视频和相关文档的话 ...

  4. Java从零到企业级电商项目实战

    欢迎关注我的微信公众号:"Java面试通关手册"(坚持原创,分享各种Java学习资源,面试题,优质文章,以及企业级Java实战项目回复关键字免费领取)回复关键字:"电商项 ...

  5. Machine Learning系列--隐马尔可夫模型的三大问题及求解方法

    本文主要介绍隐马尔可夫模型以及该模型中的三大问题的解决方法. 隐马尔可夫模型的是处理序列问题的统计学模型,描述的过程为:由隐马尔科夫链随机生成不可观测的状态随机序列,然后各个状态分别生成一个观测,从而 ...

  6. c json实战引擎六 , 感觉还行

    前言 看到六, 自然有 一二三四五 ... 为什么还要写呢.  可能是它还需要活着 : ) 挣扎升级中 . c json 上面代码也存在于下面项目中(维护的最及时) structc json 这次版本 ...

  7. Ubuntu 10.04 分辨率调整

    最近学长们看了我的本本都在问我,显卡驱动是不是出现什么问题了···分辨率这么差.当时我的分辨率是1024X768,于是我就想修改我的屏幕分辨率改成1280X800.本来很简单的事情,我做起来却非常的曲 ...

  8. C++面试总结

    1.多态       C++多态分两种--静态和动态,其中静态联编支持的多态称为编译时多态,包括重载和模板:动态联编支持的多态称为运行时多态,包括 继承和虚函数实现. 多态主要是由虚函数实现的,虚函数 ...

  9. csu 1114平方根大搜索(JAVA大小数+二分)

    1114: 平方根大搜索 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 182  Solved: 96[Submit][Status][Web Boar ...

  10. appium---【Mac】Appium-Doctor提示WARN:“ ios_webkit_debug_proxy cannot be found”解决方案

    “ ios_webkit_debug_proxy cannot be found”报错截图如下: 解决方案: 打开terminal终端,分别输入执行结束,再次运行appium-doctor即可看到运行 ...