Problem Description
There is an apple tree in front of Taotao's house. When autumn comes, n apples on the tree ripen, and Taotao will go to pick these apples.
When Taotao picks apples, Taotao scans these apples from the first one to the last one. If the current apple is the first apple, or it is strictly higher than the previously picked one, then Taotao will pick this apple; otherwise, he will not pick.
Given the heights of these apples h1,h2,⋯,hn, you are required to answer some independent queries. Each query is two integers p,q, which asks the number of apples Taotao would pick, if the height of the p-th apple were q (instead of hp). Can you answer all these queries?
Input
The first line of input is a single line of integer T (1≤T≤10), the number of test cases.
Each test case begins with a line of two integers n,m (1≤n,m≤105), denoting the number of apples and the number of queries. It is then followed by a single line of n integers h1,h2,⋯,hn (1≤hi≤109), denoting the heights of the apples. The next m lines give the queries. Each of these m lines contains two integers p (1≤p≤n) and q (1≤q≤109), as described in the problem statement.
Output
For each query, display the answer in a single line.
Sample Input
1 5 3 1 2 3 4 4 1 5 5 5 2 3
Sample Output
1 5 3
Hint
For the first query, the heights of the apples were 5, 2, 3, 4, 4, so Taotao would only pick the first apple. For the second query, the heights of the apples were 1, 2, 3, 4, 5, so Taotao would pick all these five apples. For the third query, the heights of the apples were 1, 3, 3, 4, 4, so Taotao would pick the first, the second and the fourth apples.
思路:线段树加递归,tr[rt].ans维护区间内的递增序列,tr[rt].max代表区间内的最大值,这样一来tr[rt].max=max(tr[rt<<1].max,tr[rt<<1|1].max).难点在于ans的传递,tr[rt].ans一定等于左子区间的ans加上右子区间里比左子区间max大的那个值开始的递增序列。因为线段树上都是半块半块处理的,这样每次update的时候我们就讨论一下。
令rt的左子区间的max值为M,右子区间的左子区间p最大值为K,当K小于等于M的时候,说明区间p的值都小于等于M,直接递归右区间即可,如果K>M,说明左子区间需要重新递归计算,而右子区间在递归过程中是根据左子区间p计算的,所以这里对右子区间没有影响了。tr[rt].ans=tr[rt].ans-tr[rt<<1].ans+query(p).
参考博客:https://blog.csdn.net/blessLZH0108/article/details/74839020(BZOJ 2957 重建楼房)
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct nod{
int l,r,ans;
int ma;
int mid(){
return (l+r)>>1;
}
}tr[maxn<<2];
long long h[maxn];
void build(int rt,int l,int r){
tr[rt].l=l;
tr[rt].r=r;
tr[rt].ans=0;
tr[rt].ma=0;
if(l==r) return ;
int mid=tr[rt].mid();
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
int query(int rt,int l,int r,int ma){
if(l==r) return ma<tr[rt].ma;
int mid=tr[rt].mid();
if(ma>=tr[rt<<1].ma) return query(rt<<1|1,mid+1,r,ma);
return tr[rt].ans-tr[rt<<1].ans+query(rt<<1,l,mid,ma);
}
void update(int rt,int l,int r,int k,int ma){
if(l==r) {
tr[rt].ans=1;
tr[rt].ma=ma;
return ;
}
int mid=tr[rt].mid();
if(k<=mid) update(rt<<1,l,mid,k,ma);
else update(rt<<1|1,mid+1,r,k,ma);
tr[rt].ma=max(tr[rt<<1].ma,tr[rt<<1|1].ma);
tr[rt].ans=tr[rt<<1].ans+query(rt<<1|1,mid+1,r,tr[rt<<1].ma);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i=1;i<=n;i++) {
scanf("%lld",&h[i]);
update(1,1,n,i,h[i]);
}
for(int i=1;i<=m;i++){
int k,ma;
scanf("%d%d",&k,&ma);
update(1,1,n,k,ma);
printf("%d\n",tr[1].ans);
update(1,1,n,k,h[k]);
}
}
}