线段树维护当前区间的答案和当前区间的最大值
考虑如何合并
左区间的答案显然可以被统计进去,记左区间的最大值为val
考虑右区间,右区间的左儿子的最大值<=val,则直接计算右区间的右儿子
否则右区间的右儿子的答案肯定能被计入最终答案,计算左儿子即可
递归统计
O(n log^2 n)
也可以分块(wu nao)
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,sz[550005],x[100005],y[100005];
double Max[550005];
int update(int t,int l,int r,double lim){
if (l==r) return Max[t]>lim;
int mid=(l+r)>>1;
if (Max[t<<1]<=lim) return update(t<<1|1,mid+1,r,lim);
else return sz[t]-sz[t<<1]+update(t<<1,l,mid,lim);
}
void insert(int t,int l,int r,int x,double k){
if (l==r){
sz[t]=1;
Max[t]=k;
return;
}
int mid=(l+r)>>1;
if (x<=mid) insert(t<<1,l,mid,x,k);
else insert(t<<1|1,mid+1,r,x,k);
Max[t]=max(Max[t<<1],Max[t<<1|1]);
sz[t]=sz[t<<1]+update(t<<1|1,mid+1,r,Max[t<<1]);
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1; i<=m; i++) scanf("%d%d",&x[i],&y[i]);
for (int i=1; i<=m; i++){
insert(1,1,n,x[i],(double)y[i]/x[i]);
printf("%d\n",sz[1]);
}
return 0;
}