P11750 「TPOI-1D」谢谢您。题解
这是两个时间复杂度
不考虑阈值分治,而是直接考虑对区间序列分块,设块长为
先考虑整块,设
注意到,我们从
现在考虑散块,就转化为
-
注意到本质不同的区间只有
O(n) 个,因此可以对这些区间做莫队,处理完一整个区间之后,遍历其对应的块中的所有询问并更新答案,因为一个询问最多拆到两个散块上,复杂度为O(nB+m\sqrt n) 。 -
还有一种做法是,把询问的
[l,r,k] 挂在k 上,顺次做所有的k ,我们设b_i=[a_i=k] ,那询问就是区间和,使用O(\sqrt n)-O(1) 再次分块平衡即可O(1) 查询。
这两种做法总复杂度显然都可以做到
这样总复杂度就是时间 口胡没写。
写了,莫队最后遍历常数太大,用第二种方法过的,给一个卡常前的代码。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define B 600
#define BB 500
using namespace std;
int n,m,q,cnt;
int a[200005];
int p[200005];
int t[200005];
int h[200005];
int g[200005];
int bl[200005];
int lf[200005];
int rt[200005];
int ll[200005];
int rr[200005];
bool mp[200005];
int ans[200005];
vector <int> F[200005];
vector <int> G[200005];
struct node{int l,r,x;}qq[200005];
inline void in(int &n){
n=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0'&&c<='9') n=n*10+c-'0',c=getchar();
return ;
}
int llf[200005];
int rrt[200005];
int bll[200005];
inline void add(int x,int y){
for(int i=bll[x];i<=bll[n];i++) t[i]+=y;
for(int i=x;i<=rrt[bll[x]];i++) h[i]+=y;
return ;
}
inline int ask(int x){return t[bll[x]-1]+h[x];}
int main(){
in(n),in(m),in(q);
for(int i=1;i<=n;i++) in(a[i]),F[a[i]].emplace_back(i);
for(int i=1;i<=m;i++) bl[i]=(i+B-1)/B;
for(int i=1;i<=m;i++) rt[bl[i]]=i;
for(int i=m;i>=1;i--) lf[bl[i]]=i;
for(int i=1;i<=n;i++) bll[i]=(i+BB-1)/BB;
for(int i=1;i<=n;i++) rrt[bll[i]]=i;
for(int i=n;i>=1;i--) llf[bll[i]]=i;
for(int i=1;i<=m;i++) in(ll[i]),in(rr[i]),p[i]=i;
for(int i=1;i<=q;i++) in(qq[i].l),in(qq[i].r),in(qq[i].x);
for(int i=1;i<=bl[m];i++){
for(int j=lf[i];j<=rt[i];j++) h[j]=j;
sort(h+lf[i],h+rt[i]+1,[](int x,int y){return ll[x]==ll[y]?rr[x]>rr[y]:ll[x]<ll[y];});
int R=0,mm=0;
for(int j=lf[i];j<=rt[i];j++){
if(R>=rr[h[j]]) continue;
g[++mm]=h[j];
R=max(R,rr[h[j]]);
}
for(int j=1;j<=n;j++) t[j]=h[j]=0;
int L=1;R=0;
for(int j=1;j<=mm;j++){
while(L<ll[g[j]]) t[a[L++]]--;
while(R<rr[g[j]]) t[a[++R]]++,h[a[R]]=max(h[a[R]],t[a[R]]);
}
for(int j=1;j<=q;j++) if(qq[j].l<=lf[i]&&qq[j].r>=rt[i]) ans[j]=max(ans[j],h[qq[j].x]);
}
for(int i=1;i<=q;i++) G[qq[i].x].emplace_back(i);
memset(t,0,sizeof(t));
memset(h,0,sizeof(h));
for(int i=1;i<=n;i++){
for(int v:F[i]) add(v,1);
for(int v:G[i]){
int x=0,l,r;
if(bl[qq[v].l]+1>=bl[qq[v].r]){
l=qq[v].l,r=qq[v].r;
for(int j=l;j<=r;j++) x=max(x,ask(rr[j])-ask(ll[j]-1));
ans[v]=max(ans[v],x);
continue;
}
l=qq[v].l,r=rt[bl[l]];
for(int j=l;j<=r;j++) x=max(x,ask(rr[j])-ask(ll[j]-1));
r=qq[v].r,l=lf[bl[r]];
for(int j=l;j<=r;j++) x=max(x,ask(rr[j])-ask(ll[j]-1));
ans[v]=max(ans[v],x);
}
for(int v:F[i]) add(v,-1);
}
for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
return 0;
}