[题解]UVA11235 Frequent values
没看到多测调了半天
每组数据给定\(n,q\)。接下来给出一个长度为\(n\)的不降序列\(A\)。接下来\(q\)次询问,每次询问给定\(l,r\),求\(A_{l\sim r}\)中出现最多的那个数出现了多少次。
\(1\le n,q \le 10^5\)。
序列不降,意味着一个数在序列中一定是连续存在的。
那么我们可以把连续相同的元素分成一段(游程编码)。
设一共分了\(len\)段,第\(i\)段的左边界是\(l\),右边界是\(r\)。\(A_i\)在第\(num[i]\)段。
查询时,对于输入的\(x,y\)。我们的答案就是下面三种情况的最大值:
- \(x\sim x\)所在组的右边界,即\(r[num[x]]-x+1\)。
- \(y\)所在组的左边界\(\sim y\),即\(y-l[num[y]]+1\)。
- \(x\)所在组的下一组\(\sim y\)所在组的上一组中,最大组的大小,即\(\max\limits_{num[x]<i<num[y]}(r[i]-l[i]+1)\)。这一操作可以用ST表来维护。
实现细节:
- 如果\(num[x]=num[y]\)(\(x,y\)在同一组),则直接输出\(y-x+1\)。
- 否则,答案就是上面\(3\)种情况的最大值,但需要注意调用
query(num[x]+1,num[y]-1)
,可能会出现\(num[x]+1>num[y]-1\)的情况,此时\(query\)需要返回\(0\)。
每个测试点时间复杂度\(O(n\log n+q)\)。
点击查看代码
#include<bits/stdc++.h> using namespace std; int n,q,a[100010]; int siz,cur=INT_MIN; int l[100010],r[100010],lg[100010]; int len,num[100010]; int maxx[100010][30]; void init(){ lg[0]=-1; for(int i=1;i<=len;i++) lg[i]=lg[i/2]+1,maxx[i][0]=r[i]-l[i]+1; for(int i=1;i<=lg[len];i++){ for(int j=1;j+(1<<i)-1<=len;j++){ maxx[j][i]=max(maxx[j][i-1],maxx[j+(1<<(i-1))][i-1]); } } } int query(int l,int r){ if(l>r) return 0; int t=lg[r-l+1]; return max(maxx[l][t],maxx[r-(1<<t)+1][t]); } int main(){ while(cin>>n>>q){ len=0; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++){ if(a[i]!=cur){ r[len]=i-1; l[++len]=i; cur=a[i]; } num[i]=len; } r[len]=n; init(); while(q--){ int x,y; cin>>x>>y; if(num[x]==num[y]) cout<<y-x+1<<endl; else cout<<max(max(r[num[x]]-x+1,y-l[num[y]]+1), query(num[x]+1,num[y]-1))<<endl; } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效