题意见参考博客
题意相当于问你改变一个位置之后。
从左往右扫描最大值。这个最大值会改变多少次。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
int a[N];
int n,m;
int Max(int i,int j)
{
if(a[i]>=a[j])return i;//这里需要大于等于,也就是要去找小于q的数的最左边的那个
//因为step数组的属性,只有最左边的那个数才存了东西,具体可以看如下数据进行验证
else return j;
}
/*
1
6 1
2 2 2 3 3 3
3 4
*/
int rmq[N][25];
int mm[N];//最大的小于等于i的2^mm[i],即Log(2,i)
void initRMQ(int n)
{
// mm[0] = -1;
//rmq[0][0] = 0;
for(int i=0; i<=n; i++)
{
// mm[i] = ((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
//预处理计算log(2,i)
rmq[i][0] = i;
}
for(int j=1; j<=17; j++)
for(int i=1; i+(1<<j)-1<=n; i++)
rmq[i][j] =Max(rmq[i][j-1],rmq[i+(1<<(j-1))][j-1]);
}
/*
求解从x-y区间a数组最大值
*/
int RMQ(int x,int y)
{
if(x>y)return 0;
int k = log2(y-x+1);
return Max(rmq[x][k],rmq[y+1-(1<<k)][k]);
}
int get_higher(int pos,int x)
{
int l = pos,r = n,tmp = -1;
while(l<=r)
{
int m = (l+r)>>1;
if(a[RMQ(pos,m)]>x)
{
tmp = m;
r =m-1;
}
else
{
l = m+1;
}
}
return tmp;
}
void debug(int a[],int n)
{
cout<<"数组a为"<<endl;
int top = 1;
for(int i=0;i<=n;i++)
{
if(top)top =0;
else printf(" ");
printf("%d",a[i]);
}
printf("\n");
}
int _size[N];
int ddz[N];
int pre[N];
//注意这里讲的上升序列是指题目中讲的从左到右
//遇到一个比当前值大的就进行更新。
//step数组含义 是从1开始,到
//当前数为止上升序列的长度,注意
//如果step数组不为0,那么a[i]一定是确定好的上升序列中的一个
//例如 1 2 3 4 4即使是相等,a[5]也是0;
//_size数组含义是单调栈的大小,代表从当前标号到最后上升序列的长度
//dl数组含义 是单调栈内元素的位置标号
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
//memset(_size,0,sizeof (_size));
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
initRMQ(n);
pre[1] = 1;
int cur = 1;
for(int i=2; i<=n; i++)
{
// pre[i] =0;
if(a[cur]<a[i])
{
pre[i] = pre[cur]+1;
cur = i;
}
}
//倒着跑单调栈,用size数组记录大小
int Front=0,Back =1;
for(int i=n; i>=1; i--)
{
while(Back<=Front&&a[i]>=a[ddz[Front]])Front--;
ddz[++Front] = i;
_size[i] = Front-Back+1;
}
debug(pre,n);
debug(_size,n);
debug(ddz,n);
for(int j=1; j<=m; j++)
{
int ans= 0;
int p,q;
scanf("%d%d",&p,&q);
int idx = RMQ(1,p-1);
//cout<<idx<<endl;
int key = q;
if(a[idx]>=q)
{
key = a[idx];
ans= -1;
}
int idx2 = get_higher(p+1,key);
//cout<<idx2<<endl;
if(idx2==-1)
{
ans+=pre[idx]+1;
printf("%d\n",ans);
}
else
{
ans+=pre[idx]+1+_size[idx2];
printf("%d\n",ans);
}
}
}
}