BZOJ 2724: [Violet 6]蒲公英 [分块 区间众数]
题面太美不忍不放
.gif)
分块分块
这种题的一个特点是只有查询,通常需要预处理;加入修改的话需要暴力重构预处理
预处理$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]蒲公英 [分块 区间众数]的更多相关文章
- 【BZOJ 2724】 2724: [Violet 6]蒲公英 (区间众数不带修改版本)
2724: [Violet 6]蒲公英 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1908 Solved: 678 Description In ...
- BZOJ 2724: [Violet 6]蒲公英( 分块 )
虽然AC了但是时间惨不忍睹...不科学....怎么会那么慢呢... 无修改的区间众数..分块, 预处理出Mode[i][j]表示第i块到第j块的众数, sum[i][j]表示前i块j出现次数(前缀和, ...
- BZOJ 2724 [Violet 6]蒲公英(分块)
题意 在线区间众数 思路 预处理出 f[i][j] 即从第 i 块到第 j 块的答案.对于每个询问,中间的整块直接用预处理出的,两端的 sqrtn 级别的数暴力做,用二分查找它们出现的次数.每次询问的 ...
- bzoj2724: [Violet 6]蒲公英 分块 区间众数 论algorithm与vector的正确打开方式
这个,要处理各个数的话得先离散,我用的桶. 我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数. 证明:若不是这里的数连区间的众 ...
- BZOJ 2724: [Violet 6]蒲公英
2724: [Violet 6]蒲公英 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1633 Solved: 563[Submit][Status ...
- [BZOJ 2724] [Violet 6] 蒲公英 【分块】
题目链接:BZOJ - 2724 题目分析 这道题和 BZOJ-2821 作诗 那道题几乎是一样的,就是直接分块,每块大小 sqrt(n) ,然后将数字按照数值为第一关键字,位置为第二关键字排序,方便 ...
- BZOJ.2724.[Violet 6]蒲公英(静态分块)
题目链接 区间众数 强制在线 考虑什么样的数会成为众数 如果一个区间S1的众数为x,那么S1与新区间S2的并的众数只会是x或S2中的数 所以我们可以分块先预处理f[i][j]表示第i到第j块的众数 对 ...
- 【刷题】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 ...
- 【BZOJ】2724: [Violet 6]蒲公英
2724: [Violet 6]蒲公英 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 2900 Solved: 1031[Submit][Statu ...
随机推荐
- The Blocks Problem(vector)
题目链接:http://poj.org/problem?id=1208 The Blocks Problem Time Limit: 1000MS Memory Limit: 10000K Tot ...
- 【笔记】nodejs读取JSON,数组转树
const fs = require('fs'); // --------------- 读取源文件 --------------- const originData = require('./vux ...
- Linux下采用VI编辑器删除复制或移动多行文本内容
一.删除多行 单行删除,:1(待删除行号)d 多行删除,:1,10d dd 删除光标所在行ndd删除以当前行开始的n行dw删除以当前字符开始的一个字符ndw删除以当前字符开始的n个字符d$.D删除以当 ...
- malloc函数用法
malloc函数用法 函数声明(函数原型): void *malloc(int size); 说明:malloc 向系统申请分配指定size个字节的内存空间.返回类型是 void* 类型.void* ...
- 独立成分分析(ICA)的模拟实验(R语言)
本笔记是ESL14.7节图14.42的模拟过程.第一部分将以ProDenICA法为例试图介绍ICA的整个计算过程:第二部分将比较ProDenICA.FastICA以及KernelICA这种方法,试图重 ...
- maven学习3,如何创建一个web项目
Maven学习 (三) 使用m2eclipse创建web项目 1.首先确认你的eclipse已经安装好m2eclipse的环境,可以参照上两篇Maven学习内容 2.新建一个maven的项目 ...
- 【Java提高】---枚举的应用
枚举 一.枚举和静态常量区别 讲到枚举我们首先思考,它和public static final String 修饰的常量有什么不同. 我举枚举的两个优点: 1. 保证了 ...
- Tomcat源码调试环境搭建
我们一般都是为了解决某个问题,才去看源码的.Java体系就是这点好处,源码唾手可得.遇到问题,最后的解决方法总是可以从源码中找到. 参考了网上的文章,过程整理如下: 1. 下载和导入 官网下载编译好的 ...
- Tree Recovery(由先、中序列构建二叉树)
题目来源: http://poj.org/problem?id=2255 题目描述: Description Little Valentine liked playing with binary tr ...
- HDU 2119 Matrix
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2119 解题思路: 处理数据,使用公式最小点覆盖数=最大匹配数,使用匈牙利算法求二分图最大匹配即可. ...