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

BZOJ 2957 楼房重建 分块

时间:2015-02-01 13:35:24      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:bzoj   分块   

题目大意:一个人站在(0,0)处,每次操作都会改变一栋楼的高度,问每次操作之后这个人会看到多少栋楼。


思路:将所有楼分块,在每一块内暴力维护一个单调递增的序列,这样只要这个块中的一栋楼能被看到,那么这一块内能被看到的楼肯定是一段,这样方便统计。

至于是哪一段,二分就可以了。


CODE:


#define _CRT_SECURE_NO_WARNINGS

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
#define SIZE 2010
#define EPS 1e-10
using namespace std;
#define max(a,b) ((a) > (b) ? (a):(b))

int points,asks;
int size,blocks;

int belong[MAX],start[MAX],_end[MAX];

double k[MAX];

struct Block{
	double stack[SIZE];
	int top,p;

	void Maintain() {
		top = 0;
		double _max = .0;
		for(int i = start[p]; i <= _end[p]; ++i)
			if(k[i] > _max + EPS)
				_max = stack[++top] = k[i];
	}
	int GetAns(double _max) {
		return top - (upper_bound(stack + 1,stack + top + 1,_max + EPS) - stack) + 1;
	}
}block[SIZE];

inline int GetAns()
{
	double _max = .0;
	int re = 0;
	for(int i = 1; i <= blocks; ++i) {
		re += block[i].GetAns(_max);
		_max = max(_max,block[i].stack[block[i].top]);
	}
	return re;
}

int main()
{
	cin >> points >> asks;
	size = sqrt(points);
	for(int i = 1; i <= points; ++i) {
		belong[i] = i / size + 1;
		if(!start[belong[i]])
			start[belong[i]] = i;
		_end[belong[i]] = i;
	}
	blocks = belong[points];
	for(int i = 1; i <= blocks; ++i)
		block[i].p = i;
	for(int x,y,i = 1; i <= asks; ++i) {
		scanf("%d%d",&x,&y);
		k[x] = (double)y / x;
		block[belong[x]].Maintain();
		printf("%d\n",GetAns());
	}
	return 0;
}


BZOJ 2957 楼房重建 分块

标签:bzoj   分块   

原文地址:http://blog.csdn.net/jiangyuze831/article/details/43370187

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