• uoj#187. 【UR #13】Ernd


    http://uoj.ac/problem/187

    每个点只能从时间,b+a,b-a三维都不大于它的点转移过来,将点按时间分成尽量少的一些段,每段内三维同时非严格单调,每段内的点可能因为连续选一段而产生平方的贡献,可以每段开一个单调栈维护斜率优化dp处理。

    注意到b-a和b+a同时小于可以推出时间小于,因此可以按b-a升序处理,b+a一维用树状数组维护前缀最值,处理选的点在时间上不连续的情况。

    #include<bits/stdc++.h>
    typedef long long i64;
    const int N=5e5+7;
    int _(){
        int x=0,c=getchar();
        while(c<48)c=getchar();
        while(c>47)x=x*10+c-48,c=getchar();
        return x;
    }
    int n,xs[N],xp=0,idp=0;
    i64 f[N],bit[N],ans=0;
    void maxs(i64&a,i64 b){if(a<b)a=b;}
    void ins(int x,i64 y){
        for(;x<=xp;x+=x&-x)maxs(bit[x],y);
    }
    i64 sum(int x){
        i64 y=0;
        for(;x;x-=x&-x)maxs(y,bit[x]);
        return y;
    }
    i64 F(int x){
        return f[x]+i64(x)*x;
    }
    int mem[N],*mp=mem;
    struct mq{
        int*q,p;
        void init(int sz){
            q=mp,mp+=sz;
            p=-1;
        }
        void upd(int i){
            int K=2*i+2;
            while(p>0){
                int a=q[p],b=q[p-1];
                if(F(b)-F(a)>=K*i64(b-a))--p;
                else break;
            }
            if(p>=0){
                int w=q[p],d=i+1-w;
                maxs(f[i],f[w]+i64(d)*d-1);
            }
            while(p>0){
                int a=q[p-1],b=q[p];
                i64 Fb=F(b);
                if((Fb-F(a))*(i-b)<=(F(i)-Fb)*(b-a))--p;
                else break;
            }
            q[++p]=i;
        }
    }qs[N];
    struct pos{
        int x,y,id,tp;
        void init(int a,int b,int c){
            xs[++xp]=x=a;
            y=b;
            id=c;
        }
        void upd(){
            f[id]=1+sum(x);
            qs[tp].upd(id);
            ins(x,f[id]);
        }
        bool operator<(const pos&p)const{
            return y<p.y||y==p.y&&x<p.x;
        }
        bool operator<=(const pos&p)const{
            return x<=p.x&&y<=p.y;
        }
    }ps[N];
    int main(){
        n=_();
        for(int i=1;i<=n;++i){
            int a=_(),b=_();
            ps[i].init(b+a,b-a,i);
        }
        for(int i=1,j=1;i<=n;i=j){
            for(++j;j<=n&&ps[j-1]<=ps[j];++j);
            for(qs[++idp].init(j-i);i<j;ps[i++].tp=idp);
        }
        std::sort(xs+1,xs+xp+1);
        for(int i=1;i<=n;++i){
            ps[i].x=std::lower_bound(xs+1,xs+xp+1,ps[i].x)-xs;
        }
        std::sort(ps+1,ps+n+1);
        for(int i=1;i<=n;++i)ps[i].upd();
        for(int i=1;i<=n;++i)maxs(ans,f[i]);
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    ES基本介绍
    Mybatis 读写分离简单实现
    分享一个Flink checkpoint失败的问题和解决办法
    一次“内存泄露”引发的血案
    记一次堆外内存泄漏排查过程
    MySQL主从复制读写分离,看这篇就够了!
    JVM运行时内存数据区域
    .NET MVC 页面传值方式
    jQuery 对表格内容进行搜索筛选
    泛型
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7503493.html
Copyright © 2020-2023  润新知