• 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}$,而你需要告诉他这个最小值。
    【输入格式】
    从文件 `duliu.in` 中读入数据。
    第一行,正整数$n$,自然数$m$。
    第二行,$n$ 个正整数,第 $i$ 个元素代表$d_i$。
    接下来 $m$ 行,每行三个正整数,分别代表$l_i、r_i、x_i$。
    【输出格式】
    输出到文件 `duliu.out` 中。
    输出 $m$ 行,每行一个整数,代表$min{max_{a_i le j le b_i}{d_j}}$,若没有合法区间,则输出$-1$。
    【样例输入一】
    5 2
    1 1 2 3 4
    1 5 2
    1 5 11
    【样例输出一】
    1
    2
    【样例输入二】
    5 4
    1 3 2 4 6
    1 3 3
    1 3 2
    2 4 10
    1 1 1556528051
    【样例输出二】
    2
    1
    3
    -1
    【数据范围与提示】
    保证,$n,m le 3 imes 10^5,d_i le 10^7,1 le l_i le r_i le n,x_i le 10^{18}$。

     题解

    毒瘤题目,区间价值和是 $ w=sum*len*2 $,而不是 $ sum*len $,$ j $ 不小于 $ k $

    对于以 $ l $ 为起点和以 $ r $ 为结尾的区间,可以直接二分+ RMQ 解决

    对于在中间的区间,显然是一个三维偏序,可以整体二分解决

    然而本题卡常

    记中间的区间为 $ [l_i,r_i] $,和为 $ w_i $

    可以发现,当 $ r_i>r $ 时,答案显然没有以 $ r $ 为结尾的区间优,于是就转化为二维偏序,求满足 $ l_i geq L,w_i geq x_i $ 的区间中最大值最小

    对于一个 $ a_i $,可以预处理出最大值为 $ a_i $ 的区间及它的 $ w_i $

    将询问按 $ x_i $,区间按 $ w_i $ 从大到小排序,满足 $ w_i>=x_i $

    将 $ a_i $ 记录到以位置为下标的线段树的 $ l_i $ 上,查询的时候只要查询 $ [L,P_r] $ 的最小值即可($ P_r $ 为以 $ r $ 为结尾的区间的左端点)

    时间效率:$ O(n log n) $

    代码

     1 #include<bits/stdc++.h>
     2 #define LL long long
     3 #define _(d) while(d(isdigit(ch=getchar())))
     4 using namespace std;
     5 LL R(){
     6     LL x;bool f=1;char ch;_(!)if(ch=='-')f=0;x=ch^48;
     7     _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;}
     8 const int N=3e5+5;
     9 int n,m,a[N],st[N][22],lg,tr[N<<2],tot,ans[N];
    10 LL sum[N];
    11 struct node{int x,id;}s[N];
    12 struct pig{int l,r,x;LL w;}p[N],q[N];
    13 bool cmp(node a,node b){return a.x>b.x;}
    14 bool cmp2(pig a,pig b){return a.w>b.w;}
    15 set<int> h;
    16 set<int>::iterator it;
    17 #define ls rt<<1
    18 #define rs rt<<1|1
    19 void update(int rt,int l,int r,int x,int v){
    20     if(l==r){tr[rt]=min(tr[rt],v);return;}
    21     int mid=(l+r)>>1;
    22     if(x<=mid)update(ls,l,mid,x,v);
    23     else update(rs,mid+1,r,x,v);
    24     tr[rt]=min(tr[ls],tr[rs]);
    25     return;
    26 }
    27 int query(int rt,int l,int r,int ql,int qr){
    28     if(ql<=l&&qr>=r)return tr[rt];
    29     int mid=(l+r)>>1,ans=1e9;
    30     if(ql<=mid)ans=query(ls,l,mid,ql,qr);
    31     if(qr>mid)ans=min(ans,query(rs,mid+1,r,ql,qr));
    32     return ans;
    33 }
    34 int rmq(int l,int r){
    35     int x=log2(r-l+1);
    36     return max(st[l][x],st[r-(1<<x)+1][x]);
    37 }
    38 int main(){
    39     n=R(),m=R(),lg=log2(n)+1;
    40     for(int i=1;i<=n;i++)
    41         sum[i]=(st[i][0]=a[i]=R())+sum[i-1],s[i]=(node){a[i],i};
    42     sort(s+1,s+1+n,cmp);
    43     h.insert(0),h.insert(n+1);
    44     for(int i=1,l,r;i<=n;i++){
    45         it=h.lower_bound(s[i].id);
    46         r=*it-1,it--,l=*it+1;
    47         p[i]=(pig){l,r,s[i].x,(sum[r]-sum[l-1])*(r-l+1)*2};
    48         h.insert(s[i].id);
    49     }
    50     for(int i=1;i<=m;i++){
    51         int l=R(),r=R();LL w=R();
    52         if((sum[r]-sum[l-1])*(r-l+1)*2<w)ans[i]=-1;
    53         else q[++tot]=(pig){l,r,i,w};
    54     }
    55     sort(p+1,p+1+n,cmp2),sort(q+1,q+1+tot,cmp2);
    56     memset(tr,0x3f,sizeof tr);
    57     for(int i=1;i<=lg;i++)
    58         for(int j=1;j+(1<<i)-1<=n;j++)
    59             st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]);
    60     for(int i=1,j=1;i<=tot;i++){
    61         int l=q[i].l,r=q[i].r,res=0;
    62         while(l<=r){
    63             int mid=(l+r)>>1;
    64             if((sum[mid]-sum[q[i].l-1])*(mid-q[i].l+1)*2<q[i].w) l=mid+1;
    65             else r=mid-1,res=mid;
    66         }
    67         ans[q[i].x]=rmq(q[i].l,res);
    68         l=q[i].l,r=q[i].r,res=0;
    69         while(l<=r){
    70             int mid=l+r>>1;
    71             if((sum[q[i].r]-sum[mid-1])*(q[i].r-mid+1)*2<q[i].w) r=mid-1;
    72             else l=mid+1,res=mid;
    73         }
    74         ans[q[i].x]=min(ans[q[i].x],rmq(res,q[i].r));
    75         while(j<=n&&p[j].w>q[i].w) update(1,1,n,p[j].l,p[j].x),j++;
    76         ans[q[i].x]=min(ans[q[i].x],query(1,1,n,q[i].l,res));
    77     }
    78     for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
    79     return 0;
    80 }
    View Code
  • 相关阅读:
    三国杀三字经
    window.open参数表
    捕获FormRequest安全错误的类
    SqlServer之Convert 函数应用格式化日期
    数据库区分大小写的问题
    时间字符串的比较
    char码值对应列表大全
    web.config 连接字符串 加密解密,代码方式
    关于app_offline.htm的用法
    关闭窗口的时候弹出确认对话框
  • 原文地址:https://www.cnblogs.com/chmwt/p/10584900.html
Copyright © 2020-2023  润新知