题目大意:一个人站在(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;
}