• 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;
    }
    
  • 相关阅读:
    GoldenGate Studio 12.2.1.1发布
    重构-改善既有代码的设计完整笔记系列之8
    重构-改善既有代码的设计完整笔记系列之6、7
    Java多线程开发系列-线程管理
    Java多线程开发系列-线程活性故障
    Java多线程开发系列-线程间协作
    Java多线程开发系列-基础
    了不起的Java-CompletableFuture组合异步编程
    了不起的Java-Optional替代null处理
    了不起的Java-Lambda替代设计模式
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11959869.html
Copyright © 2020-2023  润新知