传送门

题面太美不忍不放


分块分块

这种题的一个特点是只有查询,通常需要预处理;加入修改的话需要暴力重构预处理

预处理$f[i][j]$为第i块到第j块的众数,显然$f[i][j]=max{f[i][j-1],j中出现的数}$,复杂度$O(N^2/S)$,常数比较小吧

最近用$pair$上瘾了...

然后查询$[l,r]$时,整块直接查,两边不完整的枚举出现的数,然后加上整块里出现次数来更新

求整块的出现次数,可以用$v[i]$表示数字$i$出现位置,二分来找,复杂度$O(NSlogN)$

或者clj orz的论文里还有预处理的方法,预处理$s[i][x]$前i个块x的次数和$ss[i][j][x]$第i块前j个中k出现次数,貌似代码量会很大....

所以说这种vector+二分来找一个区间内某个数出现次数还是比较巧妙的呀....

然后分块一定要分$\sqrt{\frac{N}{logN}}$大小,比根号快了1倍多.....

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
#define pii pair<int, int>
#define MP make_pair
#define fir first
#define sec second
const int N=4e4+,M=;
typedef unsigned long long ll;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,Q,x,y,a[N],mp[N];
vector<int> v[N];
int pos[N],m,block;
struct _blo{int l,r;} b[M];
inline void ini(){
if(n==) block=;
else block=sqrt(n/log2(n));
m=(n-)/block+;
for(int i=;i<=n;i++) pos[i]=(i-)/block+;
for(int i=;i<=m;i++) b[i].l=(i-)*block+,b[i].r=i*block;
b[m].r=n;
}
//struct I{int x; bool operator <(const I &r) const{return x>r.x;} I(int a=0):x(a){} };
pii f[M][M];
int c[N];
struct Block{
void set(int x){
memset(c,,sizeof(c));
pii now(,);
for(int i=b[x].l;i<=n;i++){
c[a[i]]++; int t=pos[i];
now=max(now,MP( c[a[i]],-a[i] ) );//-a[i]
f[x][t]=now;
}
}
int cou(int l,int r,int x){
return upper_bound(v[x].begin(),v[x].end(),r) - lower_bound(v[x].begin(),v[x].end(),l);
}
int que(int l,int r){//printf("que %d %d\n",l,r);
pii re=f[pos[l]+][pos[r]-];
if(pos[l]==pos[r])
for(int i=l;i<=r;i++) re=max(re,MP( cou(l,r,a[i]),-a[i] ) );
else{
for(int i=l;i<=b[pos[l]].r;i++) re=max(re,MP( cou(l,r,a[i]),-a[i] ) );
for(int i=b[pos[r]].l;i<=r;i++) re=max(re,MP( cou(l,r,a[i]),-a[i] ) );
}
return -re.sec;
}
}B;
int main(){
freopen("in","r",stdin);
n=read();Q=read();
for(int i=;i<=n;i++) a[i]=mp[i]=read();
sort(mp+,mp++n); mp[]=unique(mp+,mp++n)-mp-;
for(int i=;i<=n;i++)
a[i]=lower_bound(mp+,mp++mp[],a[i])-mp , v[a[i]].push_back(i);
ini();
for(int i=;i<=m;i++) B.set(i);
int last=;
while(Q--){
int l=(read()+last-)%n+,r=(read()+last-)%n+;
if(l>r) swap(l,r);
last=mp[ B.que(l,r) ];
printf("%d\n",last);
}
}

7796ms

[2017-03-15 16:41:05]

又想了一下,$ss$其实不用预处理,查询的时候暴力算就行了

然后来享受没有$log$的优越,3372ms到第一页啦啦啦

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define pii pair<int, int>
#define MP make_pair
#define fir first
#define sec second
const int N=4e4+,M=;
typedef unsigned long long ll;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,Q,x,y,a[N],mp[N];
int pos[N],m,block;
struct _blo{int l,r;} b[M];
inline void ini(){
block=sqrt(n);
m=(n-)/block+;
for(int i=;i<=n;i++) pos[i]=(i-)/block+;
for(int i=;i<=m;i++) b[i].l=(i-)*block+,b[i].r=i*block;
b[m].r=n;
} pii f[M][M];
int c[N],s[M][N];
struct Block{
void set(int x){
memset(c,,sizeof(c));
pii now(,);
for(int i=b[x].l;i<=n;i++){
c[a[i]]++; int t=pos[i];
now=max(now,MP( c[a[i]],-a[i] ) );
f[x][t]=now;
}
for(int i=;i<=mp[];i++) s[x][i]=s[x-][i];
for(int i=b[x].l;i<=b[x].r;i++) s[x][a[i]]++;
} int t[N];
int que(int l,int r){
pii re=f[pos[l]+][pos[r]-];
if(pos[l]==pos[r]){
for(int i=l;i<=r;i++) t[a[i]]=;
for(int i=l;i<=r;i++) re=max(re,MP( ++t[a[i]],-a[i] ) );
}else{
int L=pos[l],R=pos[r]-;
for(int i=l;i<=b[pos[l]].r;i++) t[a[i]]=s[R][ a[i] ] - s[L][ a[i] ];
for(int i=b[pos[r]].l;i<=r;i++) t[a[i]]=s[R][ a[i] ] - s[L][ a[i] ];
for(int i=l;i<=b[pos[l]].r;i++) re=max(re,MP( ++t[a[i]],-a[i] ) );
for(int i=b[pos[r]].l;i<=r;i++) re=max(re,MP( ++t[a[i]],-a[i] ) );
}
return -re.sec;
}
}B;
int main(){
freopen("in","r",stdin);
n=read();Q=read();
for(int i=;i<=n;i++) a[i]=mp[i]=read();
sort(mp+,mp++n); mp[]=unique(mp+,mp++n)-mp-;
for(int i=;i<=n;i++)
a[i]=lower_bound(mp+,mp++mp[],a[i])-mp; ini();
for(int i=;i<=m;i++) B.set(i);
int last=;
while(Q--){
int l=(read()+last-)%n+,r=(read()+last-)%n+;
if(l>r) swap(l,r);
last=mp[ B.que(l,r) ];
printf("%d\n",last);
}
}

BZOJ 2724: [Violet 6]蒲公英 [分块 区间众数]的更多相关文章

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

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

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

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

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

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

  4. bzoj2724: [Violet 6]蒲公英 分块 区间众数 论algorithm与vector的正确打开方式

    这个,要处理各个数的话得先离散,我用的桶. 我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数. 证明:若不是这里的数连区间的众 ...

  5. BZOJ 2724: [Violet 6]蒲公英

    2724: [Violet 6]蒲公英 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1633  Solved: 563[Submit][Status ...

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

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

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

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

  8. 【刷题】BZOJ 2724 [Violet 6]蒲公英

    Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1 Output Sample Input ...

  9. 【BZOJ】2724: [Violet 6]蒲公英

    2724: [Violet 6]蒲公英 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 2900  Solved: 1031[Submit][Statu ...

随机推荐

  1. A + B Problem II(大数加法)

    http://acm.hdu.edu.cn/showproblem.php?pid=1002 A + B Problem II Time Limit: 2000/1000 MS (Java/Other ...

  2. Android studio启动后卡在refreshing gradle project(包解决)

    这个问题几乎每个刚使用Android studio的同学都会碰到过,网上有各式各样的方法,有的说使用本地gradle,我试过多次,每次启动android studio时还是会检查更新,所以根本上解决的 ...

  3. 应用fstream格式化输出

    我举一个我应用的例子 file.open("shoroud.jrf" ,ios_base::trunc); //打开文件,清空文件内容 if(!file.good()) { pri ...

  4. [学习OpenCV攻略][016][RedHat下安装OpenCV]

    安装环境 操作系统: Red Hat Enterprise Linux Server 6.3 相关软件: ffmpeg-0.8.15.tar.bz2.cmake-3.5.1.tar.gz.OpenCV ...

  5. 初识Spider_Man(爬爬虫)

    一:引子

  6. Oracle_insert_delete_update

    Oracle_insert_delete_update --复制表格的结构 create table temp as (select * from emp where 1=2); select * f ...

  7. 跟我一起读postgresql源码(十三)——Executor(查询执行模块之——Join节点(上))

    Join节点 JOIN节点有以下三种: T_NestLoopState, T_MergeJoinState, T_HashJoinState, 连接类型节点对应于关系代数中的连接操作,PostgreS ...

  8. html dl dt dd标签元素语法结构与使用

    dl dt dd认识及dl dt dd使用方法 标签用于定义列表类型标签. dl dt dd目录 dl dt dd介绍 结构语法 dl dt dd案例 dl dt dd总结 一.dl dt dd认识 ...

  9. navicat将多个表导出为一个sql文件

    1.shift选中多个表 2右键选择--转储sql文件---结构和数据

  10. 如何查看sublime安装了哪些插件

    你应该安装过package control. 那么只要这样:按ctrl+shift+p,输入package,选择list packages,就看到了. 或者直接查看Installed Packages ...