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

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

标程:

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. vue-loader 调用了cssLoaders方法配置了css加载器属性。

    module: { loaders: [ // 这里也是相应的配置,test就是匹配文件,loader是加载器, { test: /\.vue$/, loader: 'vue' }, { test: ...

  2. MUI上传文件的方法

    <!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. Python多态、鸭子类型

    一.多态 多态指的是一类事物有多种形态. 动物有多种形态:人,狗,猪 import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.ab ...

  4. ansible安装配置及最佳实践roles

    ansible是什么? ansible是一款轻量级配置管理工具,用于远程批量部署.安装.配置.类似的还有puppet.saltstack,各有所长,任君自选. 官方文档:http://docs.ans ...

  5. geoip 扩展包根据ip定位详情

    教程:https://laravel-china.org/courses/laravel-package/2024/get-the-corresponding-geo-location-informa ...

  6. mysql一个字符问题

    顺便记录一下在使用mysql过程中碰到的一些问题: 有时候使用脚本迁移数据时会碰到乱码的问题,即使将表字符集设置成utf8也无济于事,这个时候在执行sql之前加一句set names utf8即可.

  7. Jinja2 及 render_template 的深度用法

    是时候开始写个前端了,Flask中默认的模板语言是Jinja2 现在我们来一步一步的学习一下 Jinja2 捎带手把 render_template 中留下的疑问解决一下 首先我们要在后端定义几个字符 ...

  8. lr回放Warning -26601报错的解决方法

    问题现象: Action2.c(30): Error -26601: Decompression function  (wgzMemDecompressBuffer) failed, return c ...

  9. bzoj 1100

    思路:好脑洞啊... 把边和角转化为字符串,然后用反串跑kmp... #include<bits/stdc++.h> #define LL long long #define fi fir ...

  10. 【C#】Unicode的流言终结者和编码大揭秘

    如果你是一个生活在2003年的程序员,却不了解字符.字符集.编码和Unicode这些基础知识.那你可要小心了,要是被我抓到你,我会让你在潜水艇里剥六个月洋葱来惩罚你. 这个邪恶的恐吓是Joel Spo ...