题解:P10100 [ROIR 2023] 石头 (Day 2)
YingDragon_wjq · · 题解
注意到整个涂色过程本质上就是维护一个白色区间
考虑固定终点
现在问题转化为:给定起点和步数限制,如何判断能否在第
这启发我们用 ST 表维护区间最大值,这样就能
接下来考虑求解。对于固定的
于是可以对起点位置二分。对于
设
时间复杂度
细节详见代码。
#include<bits/stdc++.h>
#define N 100005
#define M 17
#define endl '\n'
using namespace std;
int n,q,a[N],st[M][N],lg[N];
int query(int l,int r){
if(l<1||l>r||r>n) return 1e9;
int t=lg[r-l+1];
return max(st[t][l],st[t][r-(1<<t)+1]);
}
int sum(int p,int k){
if(k==1) return 1;
if(k==0) return 0;
int res=0;
int l=p+1,r=min(n,p+k-1),ans=p;
while(l<=r){
int mid=l+r>>1;
if(query(p,mid-1)<query(mid+1,p+k)){
ans=mid;
l=mid+1;
}
else{
r=mid-1;
}
}
res+=ans-p;
l=max(1,p-k+1),r=p-1,ans=p;
while(l<=r){
int mid=l+r>>1;
if(query(mid+1,p)<query(p-k,mid-1)){
ans=mid;
r=mid-1;
}
else{
l=mid+1;
}
}
res+=p-ans;
return res+1;
}
signed main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
lg[1]=0;
for(int i=2;i<=n;i++){
lg[i]=lg[i>>1]+1;
}
for(int i=1;i<=n;i++){
st[0][i]=a[i];
}
for(int i=1;i<=lg[n];i++){
for(int j=1;j+(1<<i)-1<=n;j++){
st[i][j]=max(st[i-1][j],st[i-1][j+(1<<i-1)]);
}
}
while(q--){
int p,k;
scanf("%d%d",&p,&k);
printf("%d\n",sum(p,k)-sum(p,k-1));
}
return 0;
}