传送门biu~
可以发现能够看到的楼房满足由左至右y/x的值递增,用线段树维护递增序列。用val记录最大值,ans记录递增序列的长度。递归修改单点,先取max更新区间val值,在更新ans值时,search(num,val)函数寻找的是线段num上y/x的值大于val的递增序列的长度,递归查询更新。
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct tree{
int l,r,ans;
double val;
}a[4*100005];
void buildtree(int num,int l,int r){
a[num].l=l;a[num].r=r;
if(l==r) return;
int mid=l+r>>1;
buildtree(num<<1,l,mid);
buildtree(num<<1|1,mid+1,r);
}
int search(int num,double val){
int l=a[num].l,r=a[num].r;
if(l==r) return a[num].val>val;
if(a[num<<1].val<=val) return search(num<<1|1,val);
else return a[num].ans-a[num<<1].ans+search(num<<1,val);
}
void change(int num,int pos,double val){
int l=a[num].l,r=a[num].r,mid=l+r>>1;
if(l==r) {a[num].ans=1;a[num].val=val;return;}
if(pos<=mid) change(num<<1,pos,val);
else change(num<<1|1,pos,val);
a[num].val=max(a[num<<1].val,a[num<<1|1].val);
a[num].ans=a[num<<1].ans+search(num<<1|1,a[num<<1].val);
}
int main(){
scanf("%d%d",&n,&m);
buildtree(1,1,n);
for(int i=1;i<=m;++i){
int x,y;
scanf("%d%d",&x,&y);
change(1,x,1.0*y/x);
printf("%d\n",a[1].ans);
}
return 0;
}