BZOJ 2957: 楼房重建

线段树维护当前区间的答案和当前区间的最大值

考虑如何合并

左区间的答案显然可以被统计进去,记左区间的最大值为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;
}

  

 

posted @ 2018-11-02 13:26  ~Silent  阅读(53)  评论(0编辑  收藏
Live2D