P4198 楼房重建

传送门

很妙的思路

首先,我们可以把每一栋楼房转化为它的顶部到原点这条直线的斜率,这样就变成了从一个序列中选出一个最长上升子序列(其实不是最长上升子序列,不过可以这么理解)

考虑用线段树来维护,对于每个区间,我们维护这个区间的最大值以及这个区间的答案,那么最后的答案就是\(ans[1]\)

对于叶节点来说,最大值就是它自己,答案为\(1\)

考虑怎么合并区间。

首先左边区间能看到的答案,当前区间必然也能看到

考虑右边的区间。如果右区间的最大值小于等于左区间的最大值,那么一定会被挡住啥都看不见

如果右区间的左区间的最大值小于等于左区间的最大值,左区间肯定会被挡住啥都看不见,那么我们就递归进右区间的右区间继续找答案

如果右区间的左区间的最大值大于左区间的最大值,那么所有右区间的右区间里所有原来能看到的现在还是能看到。而左区间里继续递归找

有点绕,建议看代码理解比较好

总的复杂度为\(O(nlog^2n)\)

//minamoto
#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
int read(){
    int res,f=1;char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(int x){
    if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e5+5;
int n,m,ans[N<<2];double mx[N<<2];
#define ls (p<<1)
#define rs (p<<1|1)
int query(int p,int l,int r,double sl){
    if(mx[p]<=sl)return 0;if(l==r)return mx[p]>sl;
    int mid=(l+r)>>1;
    if(mx[ls]<=sl)return query(rs,mid+1,r,sl);
    return query(ls,l,mid,sl)+ans[p]-ans[ls];
}
void upd(int p,int l,int r,int x,double sl){
    if(l==r)return (void)(ans[p]=1,mx[p]=sl);
    int mid=(l+r)>>1;
    x<=mid?upd(ls,l,mid,x,sl):upd(rs,mid+1,r,x,sl);
    mx[p]=max(mx[ls],mx[rs]);
    ans[p]=ans[ls]+query(rs,mid+1,r,mx[ls]);
}
int main(){
//  freopen("testdata.in","r",stdin);
    n=read(),m=read();
    while(m--){
        int x=read(),y=read();
        upd(1,1,n,x,1.0*y/x);
        print(ans[1]);
    }
    return Ot(),0;
}

转载于:https://www.cnblogs.com/bztMinamoto/p/9957400.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值