题目大意:给定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;
}