https://www.luogu.org/problem/P3709
分析
从题目描述可以看出来出题人语文不行
理清题目描述后,其实是问在一个区间内取出一个严格上升数列,取完区间需要多少次
这个再思考一下,其实就是在问出现最多的数出现了多少次
由于值域1e9,我们考虑离散
由于可以离线的不带修区间操作,我们考虑莫队
离散后,times数组记录某数字出现了多少次,num数组记录有多少数字出现了i次
至于为什么涉及到答案时是O(1)的,因为当前答案失效后,它也只减少了一次出现次数啊,所以是原答案-1
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int N=2e5+10; struct Query { int l,r,id; }t[N]; int n,fn,m,fm; int a[N],b[N],times[N],num[N],id[N],ans[N],lans; bool CMP(Query a,Query b) { return id[a.l]<id[b.l]||id[a.l]==id[b.l]&&(((id[a.l]&1)^1)^(a.r<b.r)); } void Solve(int x,bool type) { if (type) { num[times[x]]--; times[x]++;num[times[x]]++; lans=max(lans,times[x]); } else { num[times[x]]--;if (lans==times[x]&&num[times[x]]==0) lans--; times[x]--;num[times[x]]++; } } 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+n+1);fn=unique(b+1,b+n+1)-b-1; for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+fn+1,a[i])-b; for (int i=1;i<=m;i++) scanf("%d%d",&t[i].l,&t[i].r),t[i].id=i; fm=sqrt(m); for (int i=1;i<=m;i++) id[i]=i/fm+(i%fm>0); sort(t+1,t+m+1,CMP); num[0]=n; int l=1,r=1;Solve(a[1],1); for (int i=1;i<=m;i++) { while (r<t[i].r) Solve(a[++r],1);while (t[i].l<l) Solve(a[--l],1); while (l<t[i].l) Solve(a[l++],0);while (t[i].r<r) Solve(a[r--],0); ans[t[i].id]=lans; } for (int i=1;i<=m;i++) printf("%d ",-ans[i]); }