思路是主席树,维护可以i到n对前面每个点做的贡献,每次二分出可以看到这个点的点的区间,然后加起来
code:
#include <bits/stdc++.h>
//#define int long long
#pragma GCC optimeze(3)
#pragma GCC optimeze(2)
#define PII pair<int, int>
#define pb push_back
#define fi first
#define se second
#define lowbit(x) (x & (-x))
using namespace std;
const int N=2e5+5;
const int M=N*100;
const int mod=1e9+7;
//const int INF=1e10;
const int base=131;
int read() {
int x=0,w=1;
char ch=0;
while(ch<'0'||ch>'9'){
if (ch=='-')w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=x*10+(ch-'0');
ch=getchar();
}
return x*w;
}
void write(int x) {
static int sta[35];
int top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
while (top) putchar(sta[--top] + 48);
}
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans*=a,ans%=mod;
a=a*a,a%=mod;
b>>=1;
}
return ans;
}
int gcd(int x,int y){
return y==0? x:gcd(y,x%y);
}
int n,h[N],tot,root[N],ls[M],rs[M],tr[M],st[19][N];
void init(){
for(int i=1;i<=n;i++)st[0][i]=h[i];
for(int i=1;i<=18;i++){
for(int j=1;j+(1<<i)<=n;j++){
st[i][j]=max(st[i-1][j],st[i-1][j+(1<<(i-1))]);
}
}
}
int qu(int l,int r){
int k=log(r-l+1)/log(2);
return max(st[k][l],st[k][r-(1<<k)+1]);
}
void add(int&p,int q,int x,int s,int t){
p=++tot;
tr[p]=tr[q]+1,ls[p]=ls[q],rs[p]=rs[q];
if(s==t)return;
int mid=(s+t)>>1;
if(mid>=x)add(ls[p],ls[p],x,s,mid);
else add(rs[p],rs[p],x,mid+1,t);
}
int ask(int l,int r,int p,int s,int t){
if(s>=l&&t<=r)return tr[p];
if(!p)return 0;
int mid=(s+t)>>1,ans=0;
if(mid>=l)ans+=ask(l,r,ls[p],s,mid);
if(mid<r)ans+=ask(l,r,rs[p],mid+1,t);
return ans;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int q;
cin>>n>>q;
for(int i=1;i<=n;i++)cin>>h[i];
init();
root[n+1]=++tot;
for(int i=n;i>=2;i--){
if(h[i]<h[i-1]){
root[i]=root[i+1];
continue;
}
int l=1,r=i-1;
while(l<r){
int mid=(l+r)>>1;
if(qu(mid,i)<=h[i])r=mid;
else l=mid+1;
}
add(root[i],root[i+1],l,1,n);
}
while(q--){
int l,r;
cin>>l>>r;
cout<<ask(1,l+1,root[r+1],1,n)<<'\n';
}
return 0;
}