码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 2597 楼房重建 分块

时间:2014-12-16 11:49:11      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:bzoj   bzoj2597   分块   

题目大意:给定n座楼,初始高度为0,每次可以改变某栋楼的高度,求每次改变高度之后从原点可以看到几栋楼

记录每栋楼楼顶与原点连线的斜率 那么一栋楼可见当且仅当前面所有楼的斜率都小于这栋楼

将n栋楼分为√(0.5*n*logn)块 每一块内维护一个单调上升子序列(注意不是LCS) 比如说4 1 2 3 5 那么维护的序列就是4 5

修改的时候块内暴力重建 然后查询顺着块撸一遍 每次记录当前的最大值 然后去下一个块中二分找到第一个比这个最大值大的值 然后统计答案&&更新最大值

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
#define EPS 1e-10
using namespace std;
struct Block{
	double elements[1010];
	int tot,l,r;
	void Rebuild();
	int Get_Ans(double& x);
}blocks[120];
int n,m,b;
double a[M];
int belong[M];
void Block :: Rebuild()
{
	int i;
	double temp=0;
	tot=0;
	for(i=l;i<=r;i++)
		if(a[i]>temp+EPS)
			temp=a[i],elements[++tot]=a[i];
}
int Block :: Get_Ans(double& x)
{
	int re=(tot+1)-(upper_bound(elements+1,elements+tot+1,x+EPS)-elements);
	if(re) x=elements[tot];
	return re;
}
int main()
{
	int i,j,x,y;
	cin>>n>>m;
	b=(int)sqrt(n*log(n)/log(2)/2);
	for(i=1;(i-1)*b+1<=n;i++)
	{
		blocks[i].l=(i-1)*b+1;
		blocks[i].r=min(i*b,n);
	}
	for(i=1;i<=n;i++)
		belong[i]=(i-1)/b+1;
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		a[x]=(double)y/x;
		blocks[belong[x]].Rebuild();
		double temp=0;
		int ans=0;
		for(j=1;blocks[j].l;j++)
			ans+=blocks[j].Get_Ans(temp);
		printf("%d\n",ans);
	}
	return 0;
}


BZOJ 2597 楼房重建 分块

标签:bzoj   bzoj2597   分块   

原文地址:http://blog.csdn.net/popoqqq/article/details/41957495

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!