题意:给你一串数字让你求严格递增的有多少个
思路:
用线段树可以提升查找的速度,tr[rt].ma就是记录当前到此的最大值,而ans就是左子树的ans加上右子树大于该值前的max值的数量
代码:
#include<bits/stdc++.h>
using namespace std;
int a[100005];
struct pp{
int l,r,ans,ma;
int mid(){
return (l+r)>>1;
}
}tr[100005<<2];
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("%d",&a[i]);
update(1,1,n,i,a[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,a[k]);
}
}
}