【洛谷P4168】蒲公英【分块】

2024-01-30 10:18
文章标签 洛谷 蒲公英 分块 p4168

本文主要是介绍【洛谷P4168】蒲公英【分块】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目大意:

题目链接:https://www.luogu.org/problemnew/show/P4168
给出一个长度为 n n n的序列, m m m次询问,求区间 [ l , r ] [l,r] [l,r]中的众数。强制在线。


思路:

以下内容参考 l y d lyd lyd《算法竞赛进阶指南》。

先离散化不解释。
分块算法一般都是以“暴力+区间预处理+暴力”的方法做的。所以,我们把 n n n分成 T T T块,每块长度 ⌊ T n ⌋ ⌊\frac{T}{n}⌋ nT
然后预处理出对于任意两个区间内的数字个数。也就是说,对于任意的 1 ≤ l ≤ r ≤ T 1\leq l\leq r\leq T 1lrT,我们用 c n t [ L ] [ R ] [ i ] cnt[L][R][i] cnt[L][R][i]表示块 L ∼ R L\sim R LR内数字 i i i的个数。
如何预处理出这一部分?

  • 方法1
    先暴力处理出所有的 c n t [ i ] [ i ] [ j ] cnt[i][i][j] cnt[i][i][j],然后用区间 d p dp dp的思想,求出所有的 c n t [ L ] [ R ] [ j ] cnt[L][R][j] cnt[L][R][j],时间复杂度 O ( T 2 n ) O(T^2n) O(T2n)
  • 方法2
    预处理出 s u m [ R ] [ i ] sum[R][i] sum[R][i]表示区间 1 ∼ R 1\sim R 1R之间 i i i的个数。然后用前缀和思想, c n t [ L ] [ R ] [ i ] = s u m [ R ] [ i ] − s u m [ L ] [ i ] cnt[L][R][i]=sum[R][i]-sum[L][i] cnt[L][R][i]=sum[R][i]sum[L][i]。时间复杂度 O ( T 2 ) O(T^2) O(T2)

同时在预处理 c n t cnt cnt的时候顺便处理出 M a x [ L ] [ R ] Max[L][R] Max[L][R],表示区间众数,然后记录众数的个数。
接下来就是如何处理答案了。
对于任意一组询问,设询问区间 [ l , r ] [l,r] [l,r],那么先记录 q , p q,p q,p分别表示 l , r l,r l,r所在的块。如果 p − q ≤ 1 p-q\leq 1 pq1,那么这两个块中间就没有多余的整块,直接朴素求众数。
否则在 c n t [ q + 1 ] [ p − 1 ] cnt[q+1][p-1] cnt[q+1][p1]的整块区间中,加上 [ l , R [ q ] ] , [ L [ p ] , r ] [l,R[q]],[L[p],r] [l,R[q]],[L[p],r]之间的数字,然后求出答案。最后再减去加上的数就可以了。


算法时间复杂度为 O ( n T 2 + m T n ) O(nT^2+\frac{mT}{n}) O(nT2+nmT),空间复杂度为 O ( n T 2 ) O(nT^2) O(nT2)。为了平均时间,不妨设 n T 2 = m T n nT^2=\frac{mT}{n} nT2=nmT,解得 T ≈ n 3 T≈\sqrt[3]{n} T3n 。此时时间复杂度约为 O ( n 5 3 ) O(n^{\frac{5}{3}}) O(n35)


代码:

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;const int N=50010;
int a[N],b[N],cnt[40][40][N],L[40],R[40],pos[N],sum[N],Max[40][40][2],be[N];
int n,m,T,x,y,len,tot,last;int ask(int l,int r)
{int ans=0,maxn=0;int q=pos[l],p=pos[r];if (p-q<=1){memset(sum,0,sizeof(sum));for (int i=l;i<=r;i++){sum[a[i]]++;if (sum[a[i]]>maxn||(sum[a[i]]==maxn&&a[i]<ans))maxn=sum[a[i]],ans=a[i];}return ans;}maxn=Max[q+1][p-1][0];ans=Max[q+1][p-1][1];for (int i=l;i<=R[q];i++){cnt[q+1][p-1][a[i]]++;if (cnt[q+1][p-1][a[i]]>maxn||(cnt[q+1][p-1][a[i]]==maxn&&a[i]<ans))maxn=cnt[q+1][p-1][a[i]],ans=a[i];}for (int i=L[p];i<=r;i++){cnt[q+1][p-1][a[i]]++;if (cnt[q+1][p-1][a[i]]>maxn||(cnt[q+1][p-1][a[i]]==maxn&&a[i]<ans))maxn=cnt[q+1][p-1][a[i]],ans=a[i];}for (int i=l;i<=R[q];i++) cnt[q+1][p-1][a[i]]--;for (int i=L[p];i<=r;i++) cnt[q+1][p-1][a[i]]--;return ans;
}int main()
{scanf("%d%d",&n,&m);for (int i=1;i<=n;i++){scanf("%d",&a[i]);b[i]=a[i];}sort(b+1,b+1+n);tot=unique(b+1,b+1+n)-b-1;for (int i=1;i<=n;i++){x=lower_bound(b+1,b+1+tot,a[i])-b;be[x]=a[i];a[i]=x;}T=(int)pow((double)n,1.0/3.0);len=n/T;if (T*len<n) T++;for (int i=1;i<=T;i++){L[i]=R[i-1]+1;R[i]=min(i*len,n);for (int j=L[i];j<=R[i];j++){cnt[i][i][a[j]]++;if (cnt[i][i][a[j]]>Max[i][i][0]||(cnt[i][i][a[j]]==Max[i][i][0]&&a[j]<Max[i][i][1])){Max[i][i][0]=cnt[i][i][a[j]];Max[i][i][1]=a[j];}pos[j]=i;}}for (int k=1;k<T;k++)for (int i=1;i<=T-k;i++){int j=i+k;int mid=(i+j)/2;for (int l=1;l<=tot;l++){cnt[i][j][l]=cnt[i][mid][l]+cnt[mid+1][j][l];if (cnt[i][j][l]>Max[i][j][0]){Max[i][j][0]=cnt[i][j][l];Max[i][j][1]=l;}}}while (m--){scanf("%d%d",&x,&y);x=(x+last-1)%n+1;y=(y+last-1)%n+1;if (x>y) swap(x,y);last=be[ask(x,y)];printf("%d\n",last);}return 0;
}

这篇关于【洛谷P4168】蒲公英【分块】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/659922

相关文章

高精度计算(代码加解析,洛谷p1601,p1303)除法待更新

目录 高精度加法 高精度减法 高精度乘法 高精度加法 我们知道在c++语言中任何数据类型都有一定的表示范围。当两个被加数很大时,正常加法不能得到精确解。在小学,我们做加法都采用竖式方法。那么我们也只需要按照加法进位的方式就能得到最终解。 8 5 6+ 2 5 5-------1 1 1 1 加法进位: c[i] = a[i] + b[i];if(c[i] >=

洛谷 凸多边形划分

T282062 凸多边形的划分 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 先整一个半成品,高精度过两天复习一下补上 #include <iostream>#include <algorithm>#include <set>#include <cstring>#include <string>#include <vector>#include <map>

能量项链,洛谷

解释:  环形dp问题还是考虑将环拉直,可以参考我上一篇文章:环形石子合并 [2 3 5 10 2] 3 5 10 将环拉直,[]内是一个有效的区间,可以模拟吸收珠子的过程,         如[2 3 5] <=>(2,3)(3,5)    2是头,3是中间,5是尾 len >= 3:因为最后[2 10 2]是最小的可以合并的有效区间 len <= n + 1因为[2 3

贝锐蒲公英远程视频监控方案:4G入网无需公网IP,跨品牌统一管理

在部署视频监控并实现集中监看时,常常会遇到各种挑战。比如:部分监控点位布线困难、无法接入有线宽带,或是没有固定公网IP,难以实现远程集中监看;已有网络质量差,传输延迟大、丢包率高,远程实时查看监控容易导致画面卡顿、丢帧,影响监看效果;一些监控区域已经有设备,不同品牌、不同设备之间缺乏统一标准和平台,无法快速实现远程统一管理、集中监看。 面对上述问题,如果替换现有网络,申请运营商专线不仅价格高

Spring Boot实现大文件分块上传

1.分块上传使用场景 大文件加速上传:当文件大小超过100MB时,使用分片上传可实现并行上传多个Part以加快上传速度。 网络环境较差:网络环境较差时,建议使用分片上传。当出现上传失败的时候,您仅需重传失败的Part。 文件大小不确定: 可以在需要上传的文件大小还不确定的情况下开始上传,这种场景在视频监控等行业应用中比较常见。 2.实现原理 实现原理其实很简单,核心就是客户端把大文件

洛谷P5490扫描线

0是最小的数字,将一个线段看成一个区间,对于一个矩形,从下扫到上,入边为1,而出边为-1,意思是将这个区间上的所有点加1(区间修改).把线段表示为Line[i],其中记录了l,r,h,tag,左右端点,高度,入边还是出边(1或-1) 那么每次区间修改后不为0的区间它的值可能是1,2,3或者是其它数字,这不好统计,可以将它转化一下,0是不是表示没有被覆盖过的地方,我们只要统计0的个数然后用总长减去

【BNU】40719 Arithmetic Progressions【分块+FFT】

传送门:【BNU】40719 Arithmetic Progressions 题目分析: 用分块+FFT强行AC了这题…… 之前一直TLE……然后改了好久把姿势改的优美点了……终于过了…… 大概思路是:我们考虑分块,假设每一块的大小为S,一共分了B块然后我们分两种情况讨论: 1.第二个数在第i块,第一个数在(1~i-1)块内,第三个数在(i+1~B)块内。 2.至少两个数在同一块内。

【HDU】5213 Lucky 【分块(在线算法)】

传送门:【HDU】5213 Lucky 题目分析: 我来说一下这题的在线做法。 首先我们将区间分成 n√ \sqrt n块,用f[x][y]表示第x块的数和第y块的数相加等于K的对数,这个可以 O(nn√) O(n \sqrt n)的预处理。然后还有g[x][y]表示在第1~x块中有的大小为y的数的个数,这个的复杂度同样 O(nn√) O(n \sqrt n)。 接下来,对于每组询问,我们

挤牛奶洛谷uasco

题目描述 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒。第二个农民在700秒开始,在 1200秒结束。第三个农民在1500秒开始2100秒结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300秒到1200秒),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300秒(从1200秒到1500秒)。

针对大数据的种子点生长——分块生长的策略

前言   在之前的种子点生长系列中,探讨了使用三种提取图像中内容部分种子点生长算法,分别是泛洪法、扫描线法和区段法。我们知道这三种算法在空间上都需要占用三维图像的空间以及相应的位图标记表的空间。有时,我们需要处理一些体积相当大的数据,这些数据都是内存中无法放下的,如数十数百GB的数据,想要获得其中图像内容信息,一般需要对图像进行分块生长。   本文使用一种比较直接的思路对数据进行分块,然