• P6958 [NEERC2017]The Great Wall


    题意:

    戳这里

    分析:

    首先由于 (k) 很大,所以我们没有办法直接求出第 (k) 个值,所以我们考虑二分答案,检验它是不是第 (k)

    那么我们考虑如何 (check) ,首先方案选择分为两种情况,为了方便起见,我们令 (c_i=c_i-a_i,b_i=b_i-a_i) ,这样 (a) 相当于是必选的,然后我们维护三个序列的前缀和

    1. 两个区间不相交

      [sum=b_{x+r-1}-b_{x-1}+b_{y+r-1}-b_{y-1} \ =(b_{x+r-1}-b_{x-1})+(b_{y+r-1}-b_{y-1}) \ =g(x)+g(y) ]

      我们枚举 (y) 查询一下 ([1,y-r]) 中满足 (g(y)+g(x)le mid)(x) 个数,二维数点问题直接树状数组

    2. 两个区间相交

      [sum=b_{y-1}-b_{x-1}+c_{x+r-1}-c_{y-1}+b_{y+r-1}-b_{x+r-1} \ =(c_{x+r-1}-b_{x-1}-b_{x+r-1})+(b_{y-1}-c_{y-1}+b_{y+r-1}) \ =f(x)+h(y) ]

      我们枚举 (y) 查询一下,([y-r+1,y-1]) 中满足 (h(y)+f(x)le mid)(x) 的个数 , 二维数点问题直接树状数组

    tip:

    看了巨佬的博客,学了一个新科技,支持前缀和查询 (0) 位置的树状数组

    代码:

    #include<bits/stdc++.h>
    #define inl inline 
    #define reg register
    #define pll pair<long long,long long>
    #define mk(x,y) make_pair(x,y)
    #define sec second
    #define fir first
    
    using namespace std;
    
    namespace zzc
    {
        typedef long long ll;
        inl ll read()
        {
            ll x=0,f=1;char ch=getchar();
            while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
            while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
            return x*f;
        }
    
        const ll maxn = 3e4+5;
        ll n,r,k,sum,ans,lef,rig,mid;
        ll a[maxn],b[maxn],c[maxn];
        pll f[maxn],g[maxn],h[maxn];
    
        namespace bit
        {
            ll c[maxn];
            inl void clear(){memset(c,0,sizeof(c));}
            inl void add(ll x,ll y){for(reg ll i=x;i<=n;i|=i+1)c[i]+=y;}
            inl ll query(ll x){ll res=0;for(reg ll i=x;i>=0;i&=i+1,--i)res+=c[i];return res;}
        }
    
        inl ll solve(ll x)
        {
            ll i,j,res=0;
            bit::clear();
            for(j=n-r,i=0;j>=0;res+=bit::query(g[j].sec-r),j--)
                for(;i<=n-r&&g[i].fir+g[j].fir<=x;i++) bit::add(g[i].sec,1);
            if(r==1) return res;
            bit::clear();
            for(j=n-r,i=0;j>=0;res+=bit::query(h[j].sec-1)-bit::query(h[j].sec-r),j--)
                for(;i<=n-r&&f[i].fir+h[j].fir<=x;i++) bit::add(f[i].sec,1);
            return res;
        }
    
        void work()
        {
            n=read();r=read();k=read();
            for(reg ll i=1;i<=n;i++) a[i]=read(),sum+=a[i];
            for(reg ll i=1;i<=n;i++) b[i]=b[i-1]+read()-a[i];
            for(reg ll i=1;i<=n;i++) c[i]=c[i-1]+read()-a[i];
            for(reg ll i=0;i<n-r+1;i++) g[i]=mk(b[i+r]-b[i],i),f[i]=mk(c[i+r]-b[i]-b[i+r],i),h[i]=mk(b[i+r]+b[i]-c[i],i);
            sort(g,g+n-r+1);sort(f,f+n-r+1);sort(h,h+n-r+1);
            lef=0;rig=c[n];
            while(lef<=rig)
            {
                mid=(lef+rig)>>1;
                if(solve(mid)<k) lef=mid+1;
                else ans=mid,rig=mid-1;
            }
            printf("%lld
    ",sum+ans);
        }
    
    }
    
    int main()
    {
        zzc::work();
        return 0;
    }
    
  • 相关阅读:
    简易httpserver 和客户端调用
    exe打包简易教程
    图像二值化和显示3D 的算法实现
    gitlab 生成标签
    Nginx 使用小结
    FFMPEG 切片过于占用cpu的问题
    神奇 linux 命令行 窗体穿越
    使用 SSH 在 Linux 上远程调试 .NET Core 实例 演示
    CentOS 7 yum 安装 Nginx 以及 TCP流转发
    Centos7 自动挂载分区硬盘 u盘的操作
  • 原文地址:https://www.cnblogs.com/youth518/p/14367702.html
Copyright © 2020-2023  润新知