zoukankan      html  css  js  c++  java
  • Gym101630G The Great Wall

    Link
    先二分答案(lim),那么我们现在要做的就是判定有多少个对((x,y))满足形成的答案不大于(lim)
    我们将所有((x,y))按区间是否相交分为两类,即一类是(yge x+r),另一类是(y<x+r)
    先考虑(yge x+r)的情况,设(f_i=sumlimits_{j=i}^{i+r-1}b_j-a_j),那么此时答案为(sumlimits_{i=1}^na_i+f_x+f_y)
    预处理前缀和之后求出(f),然后双指针+BIT计算即可。
    然后考虑(y<x+r)的情况,设(g_i=sumlimits_{j=1}^{i-1}a_j+c_j-2b_j+sumlimits_{j=i}^{i+r-1}c_j-b_j,h_i=sumlimits_{j=1}^{i-1}2b_j-a_j-c_j+sumlimits_{j=i}^{i+r-1}b_j-a_j),那么此时答案为(sumlimits_{i=1}^na_i+g_x+h_y)
    处理方法与上一部分一样。
    时间复杂度为(O(nlog nlog ans))

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<numeric>
    #include<algorithm>
    using i64=long long;
    const int N=30001;
    int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
    int n,r,m,k,t[N],p[N],q[N],s[N];
    i64 a[N],b[N],c[N],f[N],g[N],h[N];
    void add(int p){for(;p<=n;p+=p&-p)++t[p];}
    int ask(int p){int r=0;for(;p;p^=p&-p)r+=t[p];return r;}
    int query(int l,int r){return l=std::max(1,l),r=std::min(r,n),l>r? 0:ask(r)-ask(l-1);}
    int check(i64 lim)
    {
        int ans=0;
        memset(t+1,0,n<<2);
        for(int i=m,j=1;i;ans+=query(p[i]+r,m),--i) while(j<=m&&f[p[i]]+f[p[j]]<=lim) add(p[j++]);
        memset(t+1,0,n<<2);
        for(int i=m,j=1;i;ans+=query(q[i]+1,q[i]+r-1),--i) while(j<=m&&g[q[i]]+h[s[j]]<=lim) add(s[j++]);
        return ans>=k;
    }
    void solve()
    {
        i64 l=0,r=c[n]-a[n],ans=0;
        for(i64 mid;l<=r;) check(mid=(l+r)/2)? r=(ans=mid)-1:l=mid+1;
        printf("%lld",ans+a[n]);
    }
    int main()
    {
        n=read(),m=n-(r=read())+1,k=read();
        for(int i=1;i<=n;++i) a[i]=a[i-1]+read();
        for(int i=1;i<=n;++i) b[i]=b[i-1]+read();
        for(int i=1;i<=n;++i) c[i]=c[i-1]+read();
        for(int i=1;i<=m;++i) f[i]=a[i-1]-a[i+r-1]-b[i-1]+b[i+r-1],g[i]=a[i-1]-b[i+r-1]-b[i-1]+c[i+r-1],h[i]=b[i-1]-a[i+r-1]-c[i-1]+b[i+r-1],p[i]=q[i]=s[i]=i;
        std::sort(p+1,p+m+1,[](int i,int j){return f[i]<f[j];}),std::sort(q+1,q+m+1,[](int i,int j){return g[i]<g[j];}),std::sort(s+1,s+m+1,[](int i,int j){return h[i]<h[j];});
        solve();
    }
    
  • 相关阅读:
    leetcode 70 Climbing Stairs
    leetcode 203 Remove Linked List Elements
    【HMM】
    【设计总结】
    【docker】导出导入容器
    【设计工具】样机图
    【设计细节】apple sound
    【产品分析】盒马生鲜 套路
    【喂到嘴经济】这个词有点意思
    【需求分类】KANO模型
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12569740.html
Copyright © 2011-2022 走看看