• bzoj4367 [IOI2014]holiday假期


    题目描述

    题解:

    很明显总体路径可以是一直向左/向右,或者先向一个方向跑几步,然后反向跑。

    所以我们可以得到四种基本运动方式:

    LGL:一直向左;

    RGR:一直向右;

    LGR:先向左,然后向右回到原点;

    RGL:先向右,然后向左回到原点。

    然后决策单调,分治求解上面四个东西,最后合并出结果。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    #define ll long long
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,st,d,a[N];
    ll to[N];
    struct Pair
    {
        int x,id;
    }p0[N];
    bool cmp(Pair a,Pair b)
    {
        return a.x<b.x;
    }
    struct ptree
    {
        int rt[N],tot,siz[N*20],ch[N*20][2];
        ll vl[N*20];
        void insert(int l,int r,int &u,int br,int qx,ll d)
        {
            u=++tot;
            ch[u][0]=ch[br][0],ch[u][1]=ch[br][1],siz[u]=siz[br]+1,vl[u]=vl[br]+d;
            if(l==r)return ;
            int mid = (l+r)>>1;
            if(qx<=mid)insert(l,mid,ch[u][0],ch[br][0],qx,d);
            else insert(mid+1,r,ch[u][1],ch[br][1],qx,d);
        }
        void build()
        {
            for(int i=1;i<=n;i++)
                insert(1,n,rt[i],rt[i-1],a[i],to[a[i]]);
        }
        ll query(int l,int r,int ul,int ur,int k)
        {
            if(siz[ur]-siz[ul]<=k)return vl[ur]-vl[ul];
            if(l==r)return vl[ur]/siz[ur]*k;
            int mid = (l+r)>>1;
            if(siz[ch[ur][1]]-siz[ch[ul][1]]>=k)return query(mid+1,r,ch[ul][1],ch[ur][1],k);
            else return vl[ch[ur][1]]-vl[ch[ul][1]]+query(l,mid,ch[ul][0],ch[ur][0],k-(siz[ch[ur][1]]-siz[ch[ul][1]]));
        }
        ll ask(int ul,int ur,int k)
        {
            if(k<=0)return 0;
            return query(1,n,rt[ul],rt[ur],k);
        }
    }tr;
    ll lgl[N<<2],rgr[N<<2],lgr[N<<2],rgl[N<<2];
    void LGL(int l1,int r1,int l2,int r2)
    {
        int mid = (l1+r1)>>1;
        int pos=l2;ll now = 0;
        for(int i=l2;i<=r2;i++)
        {
            ll tmp = tr.ask(i-1,st-1,mid-st+i);
            if(tmp>=now)
            {
                now=tmp;
                pos=i;
            }
        }
        lgl[mid] = now;
        if(l1<mid)LGL(l1,mid-1,pos,r2);
        if(r1>mid)LGL(mid+1,r1,l2,pos);
    }
    void RGR(int l1,int r1,int l2,int r2)
    {
        int mid = (l1+r1)>>1;
        int pos=l2;ll now = 0;
        for(int i=l2;i<=r2;i++)
        {
            ll tmp = tr.ask(st,i,mid-i+st);
            if(tmp>=now)
            {
                now=tmp;
                pos=i;
            }
        }
        rgr[mid] = now;
        if(l1<mid)RGR(l1,mid-1,l2,pos);
        if(r1>mid)RGR(mid+1,r1,pos,r2);
    }
    void LGR(int l1,int r1,int l2,int r2)
    {
        int mid = (l1+r1)>>1;
        int pos=l2;ll now = 0;
        for(int i=l2;i<=r2;i++)
        {
            ll tmp = tr.ask(i-1,st-1,mid-2*st+2*i);
            if(tmp>=now)
            {
                now=tmp;
                pos=i;
            }
        }
        lgr[mid] = now;
        if(l1<mid)LGR(l1,mid-1,pos,r2);
        if(r1>mid)LGR(mid+1,r1,l2,pos);
    }
    void RGL(int l1,int r1,int l2,int r2)
    {
        int mid = (l1+r1)>>1;
        int pos=l2;ll now = 0;
        for(int i=l2;i<=r2;i++)
        {
            ll tmp = tr.ask(st,i,mid-2*i+2*st);
            if(tmp>=now)
            {
                now=tmp;
                pos=i;
            }
        }
        rgl[mid] = now;
        if(l1<mid)RGL(l1,mid-1,l2,pos);
        if(r1>mid)RGL(mid+1,r1,pos,r2);
    }
    int main()
    {
    //  freopen("4.in","r",stdin);
        n=rd(),st=rd()+1,d=rd();
        for(int i=1;i<=n;i++)p0[i].x=rd(),p0[i].id=i;
        sort(p0+1,p0+1+n,cmp);
        for(int las=-1,k=0,i=1;i<=n;i++)
        {
            if(las!=p0[i].x)
            {
                las=p0[i].x;
                to[++k]=las;
            }
            a[p0[i].id]=k;
        }
        tr.build();
        LGL(1,d,1,st);
        LGR(1,d,1,st);
        RGL(1,d,st,n);RGR(1,d,st,n);
        ll ans = 0;
        for(int i=0;i<=d;i++)
            ans=max(ans,max(lgl[i]+rgl[d-i],rgr[i]+lgr[d-i]));
        for(int i=0;i<d;i++)
            ans=max(ans,max(lgl[i]+rgl[d-i-1],rgr[i]+lgr[d-i-1])+to[a[st]]);
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    QLineEdit控件只能输入数字--QValidator结合正则
    谈 Linux,Windows 和 Mac (转自 王垠)
    看了王垠的文章《对Rust语言的分析》
    unsigned int 无符号整型的使用
    Qt布局Layout设置完全填充(设置Layout的Margin值)
    C#批量删除Mysql中相同前缀的表格
    libusb
    NPOI -- 读取excel表格中的时间格式
    spring项目启动执行
    kafka安全(一)SASL+ACL
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10218239.html
Copyright © 2020-2023  润新知