[Ynoi2019模拟赛]Yuno loves sqrt technology III
题目大意:
给你一个长为n的序列a,m次询问,每次查询一个区间的众数的出现次数,强制在线。
解题思路:
众所周知lxl是个毒瘤,Ynoi道道都是神仙题
首先得离散化。
分块后,预处理Fi,j表示第i∼j块的众数的出现次数。此处要用一个桶,空间复杂度O(n),时间复杂度O(n√n)。
用vector按顺序存每个数值所有元素的出现位置。
再记录每个元素在相应vector里的下标p。
以上空间复杂度都是O(n)的。
考虑询问,中间的直接使用预处理出的Fi,j的值即可。设当前的答案ans=Fi,j。
考虑边界的元素。
显然,由于边界的数最多2√n个,所以最多使得答案增加2√n。
我们只需要检查这些边角的元素,每次判断这些数的出现次数能否达到ans+1。
对于左边的边角元素x,我们在相应的vector里找到下标为px+ans的元素y,若y⩽,则说明该数值在范围内有至少ans+1个数,暴力++ans即可。
对于右边的边角元素x,我们在相应的vector里找到下标为p_x-ans的元素y,若y\geqslant l,则说明该数值在范围内有至少ans+1个数,暴力++ans即可。
每次询问对O(\sqrt n)个元素检查,++ans的次数为O(\sqrt n)次。所以查询的时间复杂度为O(m\sqrt n)。
总时间复杂度O((n+m)\sqrt n),空间复杂度O(n),lxl说达到了下界。
C++ Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #include<cstdio> #include<cctype> #include<vector> #include<cstring> #include<algorithm> #define siz 708 #define N 500001 class istream{ char buf[20000003],*s; public : inline istream(){ #ifndef ONLINE_JUDGE freopen ( "input.txt" , "r" ,stdin); #endif fread (s=buf,1,20000003,stdin); fclose (stdin); } inline istream&operator>>( int &rhs){ int f=rhs=0; for (;! isdigit (*s);++s)f=*s== '-' ; for (; isdigit (*s);) rhs=(rhs<<3)+(rhs<<1)+(*s++^ '0' ); if (f)rhs=-rhs; return * this ; } }cin; class ostream{ char buf[5000005],*s; public : inline ostream(){s=buf;} inline ostream&operator<<( int rhs){ if (rhs<0)*s++= '-' ,rhs=-rhs; if (rhs==0){ *s++= '0' ; return * this ; } static int w; for (w=1;w<=rhs;w*=10); for (w/=10;w;w/=10)*s++=(rhs/w)^ '0' ,rhs%=w; return * this ; } inline ostream&operator<<( const char &rhs){*s++=rhs; return * this ;} inline ~ostream(){ fwrite (buf,1,s-buf,stdout); } }cout; int n,m,L[710],R[710],bel[N],blocks,mx[710][710],ans,tot[N],wz[N],a[N]; void init(){ blocks=(n-1)/siz+1; for ( int i=1;i<=blocks;++i)L[i]=R[i-1]+1,R[i]=i*siz; R[blocks]=n; for ( int i=1;i<=blocks;++i){ memset (tot,0, sizeof tot); for ( int j=L[i];j<=R[i];++j)bel[j]=i; for ( int j=i;j<=blocks;++j){ int &F=mx[i][j]; F=mx[i][j-1]; for ( int k=L[j];k<=R[j];++k) F=std::max(F,++tot[a[k]]); } } } std::vector< int >ls,v[N]; int main(){ ls.push_back(-1); cin>>n>>m; for ( int i=1;i<=n;ls.push_back(a[i++]))cin>>a[i]; std::sort(ls.begin(),ls.end()); ls.erase(std::unique(ls.begin(),ls.end()),ls.end()); for ( int i=1;i<=n;++i)v[a[i]=std::lower_bound(ls.begin(),ls.end(),a[i])-ls.begin()].push_back(i),wz[i]=v[a[i]].size()-1; init(); memset (tot,0, sizeof tot); while (m--){ int l,r;cin>>l>>r; l^=ans,r^=ans; ans=0; if (bel[l]==bel[r]){ for ( int i=l;i<=r;++i)ans=std::max(ans,++tot[a[i]]); for ( int i=l;i<=r;++i)tot[a[i]]=0; } else { ans=mx[bel[l]+1][bel[r]-1]; for ( int i=l;i<=R[bel[l]];++i){ int it=wz[i]; while (it+ans<v[a[i]].size()&&v[a[i]][it+ans]<=r)++ans; } for ( int i=L[bel[r]];i<=r;++i){ int it=wz[i]; while (it-ans>=0&&v[a[i]][it-ans]>=l)++ans; } } cout<<ans<< '\n' ; } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Huawei LiteOS基于Cortex-M4 GD32F4平台移植
· mysql8.0无备份通过idb文件恢复数据过程、idb文件修复和tablespace id不一致处