题目描述

经典区间众数题目

然而是权限题,所以题目链接放Luogu的

题解

因为太菜所以只会$O(n*\sqrt{n}+n*\sqrt{n}*log(n))$的做法

就是那种要用二分的,并不会clj那种不带log的做法

首先数的值域为1e9肯定要离散化一下

因为数最多有40000个所以开40000个vector,存一下每个数出现的位置

预处理出每个以块的端点为左右端点的区间的众数,这种区间一共有O(block^2)个,所以可以用O(n*block)的时间复杂度来预处理

可以发现的一点是,每个区间的众数,要么是散块里面的数,要么是中间所有整块的区间众数(因为散块中出现的那些数增加了中间的整块中第二大第三大的这些区间众数的出现次数,他们就有可能篡位了)

那么我们可以在离散化之后,将每个数出现的位置存到一个vector里面,在处理散块中的数的时候,我们可以通过二分查找找出这个区间中该数出现过几次(二分查找右端点和左端点相减),效率是$O(\sqrt{n}*log(n))$

整块直接调用我们预处理出来的区间众数就可以了

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f
#define il inline namespace io { #define in(a) a=read()
#define out(a) write(a)
#define outn(a) out(a),putchar('\n') #define I_int int
inline ll read() {
ll x = , f = ; char c = getchar() ;
while( c < '' || c > '' ) { if( c == '-' ) f = - ; c = getchar() ; }
while( c >= '' && c <= '' ) { x = x * + c - '' ; c = getchar() ; }
return x * f ;
}
char F[ ] ;
inline void write( I_int x ) {
if( x == ) { putchar( '' ) ; return ; }
I_int tmp = x > ? x : -x ;
if( x < ) putchar( '-' ) ;
int cnt = ;
while( tmp > ) {
F[ cnt ++ ] = tmp % + '' ;
tmp /= ;
}
while( cnt > ) putchar( F[ -- cnt ] ) ;
}
#undef I_int }
using namespace io ; using namespace std ; #define N 100010 map< int , int > mp ;
vector< int > vt[ N ] ;
int val[ N ] , a[ N ] ;
int t[ ][ ] ;
int n , tot = ;
int block , num , bl[ N ] , L[ N ] , R[ N ] ;
int cnt[ N ] ; void pre( int x ) {
int mx = , id = ;
memset( cnt , , sizeof( cnt ) ) ;
for( int i = L[ x ] ; i <= n ; i ++ ) {
cnt[ a[ i ] ] ++ ;
if( cnt[ a[ i ] ] > mx || (cnt[ a[ i ] ] == mx && val[ a[ i ] ] < val[ id ] ) ) {
mx = cnt[ a[ i ] ] ; id = a[ i ] ;
}
t[ x ][ bl[ i ] ] = id ;
}
} void build() {
block = ;
num = n / block ;
if( n % block ) num ++ ;
for( int i = ; i <= num ; i ++ ) {
L[ i ] = (i - ) * block + ;
R[ i ] = i * block ;
}
R[ num ] = n ;
for( int i = ; i <= n ; i ++ ) bl[ i ] = (i - ) / block + ;
for( int i = ; i <= num ; i ++ ) pre( i ) ;
} int serach_ans( int l , int r , int x ) {
return upper_bound( vt[ x ].begin() , vt[ x ].end() , r ) - lower_bound( vt[ x ].begin() , vt[ x ].end() , l ) ;
} int query( int l , int r ) {
int mx = , id = t[ bl[ l ] + ][ bl[ r ] - ] ;
mx = serach_ans( l , r , id ) ;
if( bl[ l ] == bl[ r ] ) {
for( int i = l ; i <= r ; i ++ ) {
int x = serach_ans( l , r , a[ i ] ) ;
if( x > mx || (x == mx && val[ a[ i ] ] < val[ id ])) { mx = x ; id = a[ i ] ; }
}
return id ;
}
for( int i = l ; i <= R[ bl[ l ] ] ; i ++ ) {
int x = serach_ans( l , r , a[ i ] ) ;
if( x > mx || (x == mx && val[ a[ i ] ] < val[ id ])) { mx = x ; id = a[ i ] ; }
}
for( int i = L[ bl[ r ] ] ; i <= r ; i ++ ) {
int x = serach_ans( l , r , a[ i ] ) ;
if( x > mx || (x == mx && val[ a[ i ] ] < val[ id ])) { mx = x ; id = a[ i ] ; }
}
return id ;
} int main() {
n = read() ; int m = read() ;
int ans = ;
for( int i = ; i <= n ; i ++ ) {
a[ i ] = read() ;
if( mp[ a[ i ] ] == ) { mp[ a[ i ] ] = ++ tot , val[ tot ] = a[ i ] ; }
a[ i ] = mp[ a[ i ] ] ;
vt[ a[ i ] ].push_back( i ) ;
}
build() ;
for( int i = ; i <= m ; i ++ ) {
int l = read() , r = read() ;
l = (l + ans - ) % n + , r = (r + ans - ) % n + ;
if( l > r ) swap( l , r ) ;
outn( ans = val[ query( l , r ) ] ) ;
}
return ;
}

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

  1. BZOJ2724 [Violet]蒲公英(分块)

    区间众数.分块,预处理任意两块间所有数的众数,和每块中所有数的出现次数的前缀和.查询时对不是整块的部分暴力,显然只有这里出现的数可能更新答案.于是可以优美地做到O(n√n). #include< ...

  2. [Violet]蒲公英 分块

    发现写算法专题老是写不动,,,, 所以就先把我在luogu上的题解搬过来吧! 题目大意:查询区间众数,无修改,强制在线 乍一看是一道恐怖的题,仔细一看发现并没有那么难: 大致思路是这样的,首先我们要充 ...

  3. Luogu P4168 [Violet]蒲公英 分块

    这道题算是好好写了.写了三种方法. 有一个好像是$qwq$$N\sqrt(N)$的方法,,但是恳请大佬们帮我看看为什么这么慢$qwq$(后面的第三种) 注:$pos[i]$表示$i$属于第$pos[i ...

  4. [BZOJ2724][Violet 6]蒲公英

    [BZOJ2724][Violet 6]蒲公英 试题描述 输入 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1 输出 输入示 ...

  5. 【BZOJ2724】蒲公英(分块)

    [BZOJ2724]蒲公英(分块) 题面 洛谷 谴责权限题的行为 题解 分块什么的都不会,根本就没写过几次. 复杂度根本不会分析,吓得我赶快来练练. 这题要求的是区间众数,显然没有什么很好的主席树之类 ...

  6. 洛谷 P4168 [Violet]蒲公英 解题报告

    P4168 [Violet]蒲公英 题目背景 亲爱的哥哥: 你在那个城市里面过得好吗? 我在家里面最近很开心呢.昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多 ...

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

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

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

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

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

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

随机推荐

  1. 多作者wordpress博客彻底屏蔽可视化编辑

    如果你的wordpress博客支持多作者,但是难免有些作者会加入过多的链接,怎么办呢?可以考虑屏蔽可视化编辑 在 functions.php 添加如下代码即可: add_filter('user_ca ...

  2. Core Data with Mantle

    Mantle makes it easy to write a simple model layer for your Cocoa or Cocoa Touch application.  Mantl ...

  3. backreference Oracle正則表達式中的反向引用

      这是Oracle对正則表達式的backreference的描写叙述 从定义中能够看到,当匹配表达式中已()的形式将一个子串包括起来.后面就能够以\? 的形式来引用.\1相应第一个(),\2相应第二 ...

  4. vue:Group XSwitch Actionsheet,Toast控件使用

    <template> <div> <div class="vux-demo"> <img class="logo" s ...

  5. 使用vue如何默认选中单选框

    使用了vue以后,发现这真的是一个灵活高效的框架,能够轻松实现页面的实时刷新.那么,今天先聊聊单选框的使用.一般我们使用单选框,会这么写: //HTML <input type=" c ...

  6. SparkSQL UDF使用方法与原理详解

    UDF是SQL中很常见的功能,但在Spark-1.6及之前的版本,只能创建临时UDF,不支持创建持久化的UDF,除非修改Spark源码.从Spark-2.0开始,SparkSQL终于支持持久化的UDF ...

  7. PAT A+B for Polynomials[简单]

    1002 A+B for Polynomials (25)(25 分) This time, you are supposed to find A+B where A and B are two po ...

  8. 解决fiddler不能抓取eclipse发出接口请求的问题

    使用eclipse执行接口时,发现在fiddler里面抓不到这些请求. 网上找了很多资料都是让在Eclipse 中设置:Windows > Preferences > Java > ...

  9. Ignite初探

    Guava是一个很方便的本地缓存工具,但是在多节点处理的过程中,本地缓存无法满足数据一致性的问题.分布式缓存Ignite很好的解决了数据一致性,可靠性,事务性等方面的问题. Ignite支持分区方式和 ...

  10. Hive 数据类型转换

    在Hive的日常使用中经常会遇到需要对字段进行数据类型转换的情况.Hive中的数据类型转换包括隐式转换(implicit conversions)和显式转换(explicitly conversion ...