浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html
题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=2957
我们把每个楼房用直线((0,0,x,y))的斜率来表示,显然你能看见的楼房的个数就是斜率严格上升的直线的个数。
然后我们居然可以用线段树维护。
时间复杂度:(O(nlogn))
空间复杂度:(O(n))
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
int n,m;
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct segment_tree {
int cnt[maxn<<2];
double maxx[maxn<<2];
int calc(int p,int l,int r,double limit) {
if(l==r) return maxx[p]>limit;
int mid=(l+r)>>1;
if(maxx[p<<1]<limit)return calc(p<<1|1,mid+1,r,limit);
else return cnt[p]-cnt[p<<1]+calc(p<<1,l,mid,limit);
}
void change(int p,int l,int r,int pos,double v) {
if(l==r) {cnt[p]=1;maxx[p]=v;return;}
int mid=(l+r)>>1;
if(pos<=mid)change(p<<1,l,mid,pos,v);
else change(p<<1|1,mid+1,r,pos,v);
maxx[p]=max(maxx[p<<1],maxx[p<<1|1]);
cnt[p]=cnt[p<<1]+calc(p<<1|1,mid+1,r,maxx[p<<1]);
}
}T;
int main() {
n=read(),m=read();
for(int i=1;i<=m;i++) {
int x=read(),y=read();
T.change(1,1,n,x,1.0*y/x);
printf("%d
",T.cnt[1]);
}
return 0;
}