• Gym102586B Evacuation


    Link
    对于(f(l,r,x)),如果我们固定了(x),那么构造最优的(b)的方法是很简单的:
    从小到大枚举(iin[0,+infty)),尽可能地让(b_{x-i},b_{x+i})大。
    如果在(S)还没有放完的时候遇到了一个(pos otin[l,r]),那么把剩下的(S)全部放到(b_{pos})就行了。
    (xin[l,mid])那么(pos=l-1),若(xin(mid,r])那么(pos=r+1)
    不难发现(xin[l,mid])(f(l,r,x))(r)无关,(xin(mid,r])(f(l,r,x))(l)无关。
    因此设(f(l,r,x)=egin{cases}f(l,x)&xin[l,mid]\g(r,x)&xin(mid,r]end{cases})
    预处理({a_i})的前缀和以及({ia_i})的前缀和之后可以(O(1))的求出单点(f,g)
    观察可得(f,g)满足四边形不等式。
    考虑离线所有询问,对于一个形如(maxlimits_{xin[L,R]}(f ext{ or }g)(r,x))的询问,将其拆分成线段树上的(O(log n))个区间,最后对线段树的每个节点用决策单调性优化暴力枚举(x)计算即可。
    时间复杂度是(O(nlog^2n)),利用基数排序可以做到(O(nlog n))

    #include<cctype>
    #include<cstdio>
    #include<vector>
    #include<utility>
    #include<algorithm>
    char ibuf[1<<23|1],*iS=ibuf;
    using i64=long long;
    using pi=std::pair<int,int>;
    const int N=200007;
    int n,q;i64 s,s1[N],s2[N],ans[N];int bound[N];
    std::vector<pi>trans[4*N][2];
    i64 read(){i64 x=0;while(isspace(*iS))++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return x;}
    i64 sum(i64*s,int l,int r){return s[r]-s[l-1];}
    i64 cal(int pos,int r)
    {
        return r<=0? 0:pos*(sum(s1,pos-r,pos-1)-sum(s1,pos+1,pos+r))-(sum(s2,pos-r,pos-1)-sum(s2,pos+1,pos+r));
    }
    i64 cal(int o,int pos,int gap)
    {
        int f=o? 1:-1,t=o? std::min(gap+1,pos+bound[pos]+1):std::max(gap-1,pos-bound[pos]-1);
        return cal(pos,f*(t-pos)-1)+f*(t-pos)*(s-(o? sum(s1,2*pos-t+1,t-1):sum(s1,t+1,2*pos-t-1)));
    }
    void work(int o,int l,int r,std::vector<pi>&q)
    {
        if(q.empty()) return ;
        if(l==r){for(auto[pos,id]:q)ans[id]=std::max(ans[id],cal(o,l,pos));return;}
        std::vector<pi>L,R;int lim=(int)q.size()/2,pos=0;i64 t,mx=0;
        for(int i=0;i<(int)q.size();++i) if(i^lim) (i<lim? L:R).push_back(q[i]);
        for(int i=l;i<=r;++i) if((t=cal(o,i,q[lim].first))>mx) mx=t,pos=i;
        ans[q[lim].second]=std::max(ans[q[lim].second],mx),work(o,l,pos,L),work(o,pos,r,R);
    }
    #define ls p<<1
    #define rs p<<1|1
    #define mid ((l+r)/2)
    void update(int p,int l,int r,int L,int R,int o,int pos)
    {
        if(L>r||l>R||L>R) return ;
        if(L<=l&&r<=R) return trans[p][o].emplace_back(o? R:L,pos),void();
        update(ls,l,mid,L,R,o,pos),update(rs,mid+1,r,L,R,o,pos);
    }
    void solve(int p,int l,int r)
    {
        if(l^r) solve(ls,l,mid),solve(rs,mid+1,r);
        for(int i=0;i<2;++i) std::sort(trans[p][i].begin(),trans[p][i].end()),work(i,l,r,trans[p][i]);
    }
    #undef ls
    #undef rs
    int find(int pos)
    {
        int l=0,r=std::min(n-pos,pos-1),ans=-1;
        while(l<=r) sum(s1,pos-mid,pos+mid)<s? ans=mid,l=mid+1:r=mid-1;
        return ans;
    }
    int main()
    {
        fread(ibuf,1,1<<23,stdin),n=read(),s=read();
        for(int i=1;i<=n;++i) {i64 x=read();s1[i]=s1[i-1]+x,s2[i]=s2[i-1]+i*x;}
        q=read();
        for(int i=1,l,r;i<=q;++i) l=read(),r=read(),update(1,1,n,l,mid,0,i),update(1,1,n,mid+1,r,1,i);
        for(int i=1;i<=n;++i) bound[i]=find(i);
        solve(1,1,n);
        for(int i=1;i<=q;++i) printf("%lld
    ",ans[i]);
    }
    
  • 相关阅读:
    三、sersync+rsync实现服务器文件实时同步
    二、Linux实时同步软件之inotify
    一、rsync基础原理
    Samba实战
    DHCP企业实战
    NTP服务器企业实战
    Vsftpd服务器原理及部署
    Python的五大数据类型的作用、定义方式、使用方法,两种交互式方式,格式化输出的三种方式练习。
    pycharm快捷键,变量,字符串,类型的操作方法
    python基础归纳练习 python两种方式,垃圾回收机制,小数整池,数字类型,字符串类型。
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12800124.html
Copyright © 2020-2023  润新知