zoukankan      html  css  js  c++  java
  • dtoj#4263. duliu

    题目描述:

    小 D 喜欢出毒瘤题毒人。当然,他的毒瘤更多体现在若干个难题组合在同一场比赛时。

    小 D 脑中有 $n$ 个毒瘤题 idea,第 $i$ 个的毒值为$d_i$。当第 $i$ 个题和第 $j$ 个题同时出现在一场比赛中,会产生$f(i,j) = d_i + d_j$ 的毒性。

    小 D 决定用这些题在 YLOJ 上办 $m$ 场在线比赛。

    • 由于这个 OJ 还在~~咕咕~~开发,YLOJ Extremelyhard Round #i 选取的题目编号集合只能为 $[l_i,r_i]$ 的一个非空子区间 $[a_i,b_i]$。

    • 因为这个 round 是 extremelyhard 的,所以需要满足$sumlimits_{a_i le j,k le b_i} f(j,k) ge x_i$。

    • 不过,为了防止题目过分毒瘤而被喷,小 D 希望最小化$max_{a_i le j le b_i} {d_i}$,而你需要告诉他这个最小值。

    算法标签:线段树

    思路:

    对于一个区间的答案,可以分为三类,一类是以区间的左端点作为选择的区间作为左端点,一类是以区间的右端点作为选择区间的右端点,一类是左右端点在区间中间,受某个最大值的限制而不能扩大区间。

    因为权值都是正数,所以对于一个选择的区间如果固定左端点,恰好满足总和限制的最小的区间最优,根据这个可以先二分计算出第一类和第二类的答案。

    考虑第三类,我们对于每一个点求出它作为最大值可以延伸的最大区间。然后当这个区间被询问区间包含的时候,可以对答案造成贡献,但是这样是三维的。我们会发现如果你选择左端点在询问左端点和这个询问第二类求的答案区间的左端点左侧,这个时候你的答案一旦超过询问区间,这个答案一定没有单独取右区间优,所以只需要满足左端点在范围内,区间权值大于询问。是一个二维偏序,可以用线段树维护得到答案。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define LL long long
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=3e5+5,inf=1e9;
    int n,m,a[N],res[N],tot,Lg[N],st[N][20];
    LL sum[N];int mn[N<<2];
    struct node{
        int l,r,ll,id;LL val;
    }t[N];
    struct data{
        int l,r,mx;LL val;
    }g[N];
    il LL read(){
       LL x,f=1;char ch;
       _(!)ch=='-'?f=-1:f;x=ch^48;
       _()x=(x<<1)+(x<<3)+(ch^48);
       return f*x;
    }
    bool cmp(node t1,node t2){
        return t1.val>t2.val;
    }
    bool cmp1(data t1,data t2){
        return t1.val>t2.val;
    }
    il int getmax(int l,int r){
        if(l>r)swap(l,r);int k=Lg[r-l+1];
        return max(st[l][k],st[r-(1<<k)+1][k]);
    }
    il int getl(int x,int v){
        int l=1,r=x,res=x;
        while(l<=r){
            int mid=(l+r)>>1;
            if(getmax(mid,x)<=v)res=mid,r=mid-1;
            else l=mid+1;
        }
        return res;
    }
    il int getr(int x,int v){
        int l=x,r=n,res=x;
        while(l<=r){
            int mid=(l+r)>>1;
            if(getmax(mid,x)<=v)res=mid,l=mid+1;
            else r=mid-1;
        }
        return res;
    }
    il LL cal(int l,int r){
        return (sum[r]-sum[l-1])*(r-l+1)*2;
    }
    il int gl(int ql,int qr,LL v){
        int l=ql,r=qr,res=ql;
        while(l<=r){
            int mid=(l+r)>>1;
            if(cal(ql,mid)>=v)res=mid,r=mid-1;
            else l=mid+1;
        }
        return res;
    }
    il int gr(int ql,int qr,LL v){
        int l=ql,r=qr,res=qr;
        while(l<=r){
            int mid=(l+r)>>1;
            if(cal(mid,qr)>=v)res=mid,l=mid+1;
            else r=mid-1;
        }
        return res;
    }
    il void insert(int x,int l,int r,int pos,int v){
        if(l==r){mn[x]=min(mn[x],v);return;}
        int mid=(l+r)>>1;
        if(pos<=mid)insert(x<<1,l,mid,pos,v);
        else insert(x<<1|1,mid+1,r,pos,v);
        mn[x]=min(mn[x<<1],mn[x<<1|1]);
    }
    il int query(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return mn[x];
        int mid=(l+r)>>1;int res=inf;
        if(ql<=mid)res=query(x<<1,l,mid,ql,qr);
        if(mid<qr)res=min(res,query(x<<1|1,mid+1,r,ql,qr));
        return res;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)st[i][0]=a[i]=read(),sum[i]=sum[i-1]+a[i];
        for(int i=2;i<=n;i++)Lg[i]=Lg[i>>1]+1;
        for(int j=1;j<=Lg[n];j++)for(int i=1;i+(1<<j)-1<=n;i++)
            st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
        for(int i=1;i<=n;i++){
            int l=getl(i,a[i]),r=getr(i,a[i]);
            LL v=(sum[r]-sum[l-1])*(r-l+1)*2;
            g[i]=(data){l,r,a[i],v};
        }
        for(int i=1;i<=m;i++){
            int l=read(),r=read();LL x=read();
            if((sum[r]-sum[l-1])*(r-l+1)*2<x)res[i]=-1;
            else{
                int ll=gl(l,r,x),rr=gr(l,r,x);
                t[++tot]=(node){l,r,rr,i,x};
                res[i]=min(getmax(l,ll),getmax(rr,r));
            }
        }
        sort(t+1,t+1+tot,cmp);sort(g+1,g+1+n,cmp1);
        int now=1;
        for(int i=1;i<=n*4;i++)mn[i]=inf;
        for(int i=1;i<=tot;i++){
            while(g[now].val>=t[i].val){
                insert(1,1,n,g[now].l,g[now].mx),now++;
            }
            res[t[i].id]=min(res[t[i].id],query(1,1,n,t[i].l,t[i].ll));
        }
        for(int i=1;i<=m;i++)printf("%d
    ",res[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    壁纸网站收藏
    LaTeX公式学习
    最简单的音乐播放器,实现播放器基本功能
    计算机视觉领域的牛人博客、研究机构、博客
    视频压缩编码和音频压缩编码的基本原理
    MPEG-4 压缩编码标准
    视频编码标准简介
    视频压缩编码的基本原理
    数字视频原理
    视频压缩编码综述
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10577660.html
Copyright © 2011-2022 走看看