Luogu P4198 楼房重建

题目
考虑每个楼房的顶楼到((0,0))的斜率(k),那么能看到的楼房就是满足前面的(k)都比它自己的(k)小的。
考虑线段树,每个节点维护当前区间内的最大的(k)(记为(mx)),和把当前这段区间单独拿出来考虑的答案(记为(val))。
我们要支持的就是单点修改和全局查询。全局查询就是(1)这个节点的答案。
单点修改我们可以直接到底层然后往上pushup回来,维护(mx)非常容易,但是维护(val)并不好做。
假如现在有一个线段树节点(p),我们要合并其左右儿子(ls,rs)所代表的的区间然后求答案。
首先我们知道(val_{ls})会全部计算进来,但是(rs)会受到(mx_{ls})的影响导致答案变小。
我们考虑在线段树上从(rs)往下递归计算这个答案。
假设当前递归到的节点为(p'),左右儿子分别为(ls',rs')
如果(mx_{p'}le mx_{ls})小,那么这一段区间的答案都是(0)
如果(p')所代表的区间的第一个(k)(mx_{ls})大,那么这一段区间不受影响,答案不变。
否则我们再看当前(ls',rs')所代表的区间。
如果(mx_{ls'}le mx_{ls}),那么我们可以直接往(rs')递归,因为此时(ls')所代表的区间不会有任何影响。
否则我们递归计算(ls')的答案,而(rs')的答案就是(val_{p'}-val_{ls'})。因为(mx_{ls'}>mx_{ls}),所以(mx_{ls})相当于没有影响,(rs')所代表区间的答案就是和(ls')放在一起的贡献的答案。
这样每次修改我们的复杂度都为(O(log^2 n)),所以总复杂度为(O(nlog^2 n))

#include<cstdio>
#include<cctype>
#include<iostream>
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
#define db double
using namespace std;
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[11],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
    void Put(char x){*oS++=x;if(oS==oT)Flush();}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
    void write(int x){int top=0;while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('
');}
}
using namespace IO;
const int N=100007;
int n,m,val[N<<2];db a[N],mx[N<<2];
void pushup(int p){mx[p]=max(mx[ls],mx[rs]);}
int query(int p,int l,int r,db k)
{
    if(mx[p]<=k) return 0;
    if(a[l]>k) return val[p];
    return mx[ls]<=k? query(rs,mid+1,r,k):query(ls,l,mid,k)+val[p]-val[ls];
}
void update(int p,int l,int r,int x,db k)
{
    if(l==r) return (void)(val[p]=1,mx[p]=k);
    (x<=mid? update(ls,l,mid,x,k):update(rs,mid+1,r,x,k)),pushup(p),val[p]=val[ls]+query(rs,mid+1,r,mx[ls]);
}
int main()
{
    n=read(),m=read();
    for(int x,y;m;--m) x=read(),y=read(),a[x]=(db)y/x,update(1,1,n,x,a[x]),write(val[1]);
    return Flush(),0;
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11959869.html