BZOJ2724 [Violet 6]蒲公英 解题报告【数据结构】【分块】
2017-07-18 20:20
399 查看
Description
Input
修正一下
l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1
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 <= 50000
解题报告
传说中这是一道分块的经典题。
我们不难看出,这道题要我们强制在线,加上只是查找众数没有更改,不方便合并区间,让人不由自主地想到了分块。那么这个题用分块怎么做呢?
我们又均值不等式得,分成sqrt(n)块时时间复杂度最低。我们先预处理出几个值:
-f[i][j] 存储这样一个pair:(第i到第j块分块出现的次数最多的数的次数,这个数的值的负值)。由于我们知道比较pair的最大值是先比first再比second,这样一来就可以保证这个数组是最优的。
-s[i][j] 代表前i块中j这个数出现的次数的和(前缀和)。
由于这个题不可能直接开一个筒来存储每一个数出现的次数,我们的方法是先将原数组排序,离散化,再将进行这些操作之前的这个数组每个元素的排名存储下来。往后我们存储次数的时候就直接存储排名,而非元素本身。
要点似乎就是这些,代码如下:
Input
修正一下
l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1
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 <= 50000
解题报告
传说中这是一道分块的经典题。
我们不难看出,这道题要我们强制在线,加上只是查找众数没有更改,不方便合并区间,让人不由自主地想到了分块。那么这个题用分块怎么做呢?
我们又均值不等式得,分成sqrt(n)块时时间复杂度最低。我们先预处理出几个值:
-f[i][j] 存储这样一个pair:(第i到第j块分块出现的次数最多的数的次数,这个数的值的负值)。由于我们知道比较pair的最大值是先比first再比second,这样一来就可以保证这个数组是最优的。
-s[i][j] 代表前i块中j这个数出现的次数的和(前缀和)。
由于这个题不可能直接开一个筒来存储每一个数出现的次数,我们的方法是先将原数组排序,离散化,再将进行这些操作之前的这个数组每个元素的排名存储下来。往后我们存储次数的时候就直接存储排名,而非元素本身。
要点似乎就是这些,代码如下:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> using namespace std; const int N=4e4; const int M=350; int n,m,blk,cnt; int lasans; int a[N+5],b[N+5],c[N+5],bl[N+5],L[M+5],R[M+5],s[M+5][N+5]; pair<int,int>f[M+5][M+5]; int temp[N+5]; int query(int lf,int rg) { pair<int,int>ret=f[bl[lf]+1][bl[rg]-1]; if(bl[lf]==bl[rg])//在同一块里边,暴力 { for(int i=lf;i<=rg;i++)temp[b[i]]=0; for(int i=lf;i<=rg;i++)ret=max(ret,make_pair(++temp[b[i]],-b[i])); } else//不再同一块里,答案要么就是f[bl[lf]+1][bl[rg]-1],要么就是不再上述块中的数在[lf,rg]中出现的次数 { for(int i=lf;i<=R[bl[lf]];i++)temp[b[i]]=s[bl[rg]-1][b[i]]-s[bl[lf]][b[i]];//左边的零头中的元素在整块内的个数 for(int i=L[bl[rg]];i<=rg;i++)temp[b[i]]=s[bl[rg]-1][b[i]]-s[bl[lf]][b[i]];//右边的零头中的元素在整块内的个数 for(int i=lf;i<=R[bl[lf]];i++)ret=max(ret,make_pair(++temp[b[i]],-b[i]));//左边的零头中的元素在查询区间内的个数 for(int i=L[bl[rg]];i<=rg;i++)ret=max(ret,make_pair(++temp[b[i]],-b[i]));//右边的零头中的元素在查询区间内的个数 } return -ret.second; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i]; sort(a+1,a+1+n); a[0]=unique(a+1,a+1+n)-a-1;//离散化 for(int i=1;i<=n;i++) b[i]=lower_bound(a+1,a+1+a[0],b[i])-a;//在b数组中存储排名 blk=sqrt(n); if(n%blk)cnt=n/blk+1; else cnt=n/blk; for(int i=1;i<=n;i++)bl[i]=(i-1)/blk+1; for(int i=1;i<=cnt;i++)L[i]=(i-1)*blk+1,R[i]=i*blk; R[cnt]=n; for(int i=1;i<=cnt;i++) { memset(c,0,sizeof(c)); pair<int,int>now(0,0); for(int j=L[i];j<=n;j++) { c[b[j]]++; now=max(now,make_pair(c[b[j]],-b[j]));//计算出第i块到第j块的答案和他的值 f[i][bl[j]]=now; } for(int j=1;j<=a[0];j++)s[i][j]=s[i-1][j]; for(int j=L[i];j<=R[i];j++)s[i][b[j]]++;//前缀和 } while(m--) { int l,r; scanf("%d%d",&l,&r); int lf=(l+lasans-1)%n+1,rg=(r+lasans-1)%n+1; if(lf>rg)swap(lf,rg); lasans=a[query(lf,rg)];//返回的只是排名 printf("%d\n",lasans); } return 0; }
相关文章推荐
- BZOJ1086 [SCOI2005]王室联邦 解题报告【数据结构(?)】【树分块】【DFS】
- BZOJ2453 维护队列 解题报告【数据结构】【分块】
- Cdqz_Openjudge1010 Challenge 10 解题报告【数据结构】【分块】
- ZOJ2112 Dynamic Rankings 解题报告【数据结构】【分块】
- BZOJ3343 教主的魔法 解题报告【数据结构】【分块】
- BZOJ2002 [Hnoi2010]Bounce 弹飞绵羊 解题报告【数据结构】【分块】
- 20110719数据结构10级复习赛题级解题报告ccnuoj
- Pku acm 1469 COURSES 数据结构题目解题报告(十一)---- 匈牙利算法求二分图的最大匹配
- BZOJ3790 神奇项链 解题报告【字符串】【Manacher】【树状数组】【数据结构优化DP】
- Pku acm 2239 Selecting Courses 数据结构题目解题报告(十二)---- 匈牙利算法求二分图的最大匹配
- BZOJ 2131 数据结构优化DP 解题报告
- CodeVS1690 开关灯 解题报告【数据结构】【线段树】
- Pku acm 1274 The Perfect Stall 数据结构题目解题报告(十三)---- 匈牙利算法求二分图的最大匹配
- 【解题报告】openjudge DNA排序 数据结构与算法mooc 内排序
- Pku acm 1062 昂贵的聘礼 数据结构题目解题报告(七)—单源最短路径:Dijkstra算法
- Pku acm 2536 Gopher II 数据结构题目解题报告(十四)---- 匈牙利算法求二分图的最大匹配
- Pku acm 1125 Stockbroker Grapevine 数据结构题目解题报告(八)---- 弗洛伊德(floyd)算法
- Pku acm 2771 Guardian of Decency 数据结构题目解题报告(十五)---- 匈牙利算法求二分图的最大匹配
- Pku acm 3041 Asteroids 数据结构题目解题报告(十六)---- 匈牙利算法求二分图的最大匹配
- Pku acm 3253 Fence Repair 数据结构题目解题报告(一) ----哈夫曼数