版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37632935/article/details/81984014
题意:给出n个苹果树的高度,taotao从第一个苹果开始摘苹果,他只能摘当前高度大于前面所有苹果树的苹果。
若干次查询每次他会问你如果把第q颗树的苹果高度改为p,他可以摘多少苹果。
思路:维护两个数组,pre从1位置到i能摘多少苹果,back记录从i位置开始到结尾能摘多少苹果。第一个数组很好维护,第二个数组我们需要找前面第一个大于他的位置,那么就涉及到区间最值查询,可以用线段树解决。
维护好这两个数组后,答案初值赋值为pre[q-1],每次查询把q位置修改为p,查询[1,q-1]最大数p的位置pos,然后比较a[pos]和p的大小,如果a[pos]<p那么ans++,那么[1,q]区间就解决了,还剩下[q+1,n]区间,q位置之后对答案有贡献的苹果树的高度肯定都是大于p的,我们查询第一个大于p的位置pos,back[pos]就是后一部分的答案。注意特判1和n的位置。
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn=1e5+10;
int a[maxn],tree[maxn<<2],pre[maxn],back[maxn],pos;
int n;
void build(int l,int r,int k)
{
if(l==r)
{
tree[k]=a[l];
return ;
}
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
tree[k]=max(tree[k<<1],tree[k<<1|1]);
return ;
}
void query_max(int L,int R,int l,int r,int k) //区间最值位置
{
if(L==R)
{
//printf("--%d\n",L);
if(a[pos]<a[L]) pos=L;
return ;
}
int mid=(L+R)>>1;
if(l<=L&&r>=R)
{
if(tree[k<<1]>=tree[k<<1|1]) query_max(L,mid,l,r,k<<1);
else query_max(mid+1,R,l,r,k<<1|1);
return ;
}
if(r>mid) query_max(mid+1,R,l,r,k<<1|1);
if(l<=mid) query_max(L,mid,l,r,k<<1);
}
void query_first(int L,int R,int l,int r,int k,int v) //区间第一个大于v的位置.
{
if(L==R)
{
pos=min(pos,L);return ;
}
int mid=(L+R)>>1;
if(l<=L&&r>=R)
{
if(tree[k<<1]>v) query_first(L,mid,l,r,k<<1,v);
else if(tree[k<<1|1]>v) query_first(mid+1,R,l,r,k<<1|1,v);
return ;
}
if(r>mid&&tree[k<<1|1]>v) query_first(mid+1,R,l,r,k<<1|1,v);
if(l<=mid&&tree[k<<1]) query_first(L,mid,l,r,k<<1,v);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int ma=-1;
for(int i=1;i<=n;i++)
{
pre[i]=pre[i-1];
if(a[i]>ma)pre[i]++;
ma=max(ma,a[i]);
}
build(1,n,1);
for(int i=n;i>=1;i--)
{
pos=INF;
query_first(1,n,i,n,1,a[i]);
if(pos==INF) back[i]=1;
else back[i]=back[pos]+1;
}
while(m--)
{
int ans=1;int p,q;
scanf("%d%d",&p,&q);
pos=1;
if(p!=1){
query_max(1,n,1,p-1,1);
ans=pre[p-1];
if(q>a[pos]) ans++;
else q=a[pos];
}
//printf("%d %d\n",pos,q);
pos=INF;
if(p!=n)
query_first(1,n,p+1,n,1,q);
if(pos!=INF) ans+=back[pos];
printf("%d\n",ans);
}
}
return 0;
}