题解:AT_abc248_h [ABC248Ex] Beautiful Subsequences
这么爽。
分析
拿到这种题的时候相信你已经秒了,因为这题纯套路。
式子的
考虑序列上分治。定义
难点在
对于第
所以任意一个
对于第
可以用任意方式维护,这里我使用的是离线后树状数组。
对于第
也可以用任意方式维护。
复杂度为
代码
il void work(int l,int r){
if(l==r){
ans+=(a[l]-a[l]-(r-l+1)<=K);
return ;
}
int mid=l+r>>1;
work(l,mid),work(mid+1,r);
for(re int i=mid;i<=r+1;++i){
v1[i].clear(),
v2[i].clear(),
v3[i].clear();
}
Max[mid+1]=Min[mid+1]=a[mid+1];
for(re int i=mid+2;i<=r;++i){
Max[i]=max(Max[i-1],a[i]),
Min[i]=min(Min[i-1],a[i]);
}
int mx=a[mid],mi=a[mid];
for(re int L=mid,j=mid,k=mid;L>=l;--L){
mi=min(mi,a[L]),mx=max(mx,a[L]);
while(j+1<=r&&Min[j+1]>=mi) ++j;
while(k+1<=r&&Max[k+1]<=mx) ++k;
ans+=max(0ll,min(j,k)-max(mx-mi+L-1-K,mid+1)+1);//1
if(j<=k){//2.1
int s=+mx+L-1-K;
v1[min(j,k)].push_back({s,-1});
v1[max(j,k)].push_back({s, 1});
}
else{//2.2
int s=-mi+L-1-K;
v2[min(j,k)].push_back({s,-1});
v2[max(j,k)].push_back({s, 1});
}
int s_=L-1-K;
v3[max(j,k)+1].push_back(s_);//3
}
for(re int R=mid+1;R<=r;++R){//2.1
add(Min[R]+R,1);
for(auto x:v1[R]) ans+=x.y*query(x.x);
}
for(re int R=mid+1;R<=r;++R) add(Min[R]+R,-1);
for(re int R=mid+1;R<=r;++R){//2.2
add(R-Max[R],1);
for(auto x:v2[R]) ans+=x.y*query(x.x);
}
for(re int R=mid+1;R<=r;++R) add(R-Max[R],-1);
for(re int R=r;R>=mid+1;--R){//3
add(R+Min[R]-Max[R],1);
for(auto x:v3[R]) ans+=query(x);
}
for(re int R=r;R>=mid+1;--R) add(R+Min[R]-Max[R],-1);
return ;
}