zoukankan      html  css  js  c++  java
  • BZOJ2687: 交与并

    $n leq 1e6$个区间,定义一个区间集合的权值为:并集大小-交集大小。求一个权值最大的大小至少为2的集合。

    好题。

    在一个区间集合中,可以发现除了左右端点涉及的区间外,里面剩余的区间越少,并集不会变但交集会越大,因此答案会更优。但我们需要集合大小至少为2,因此变成选两个区间。

    左右端点可能涉及一个或两个区间。前者要求选中两个包含关系的集合,后者则不包含。

    包含:

    按右端点排序后,对每个$i$,求$L_j geq L_i$的最大区间,$j<i$。

    其实不必这样。当两个区间成包含关系时,小区间和其他区间不可能比大区间和其他间更优(画画图分分类),因此小区间贡献完一次就直接删掉。可以用个栈。

    不包含:

    前面说被包含的区间在这没贡献了,删之,得到一个$R$递增$L$递增的区间序列。排序之。

    然后可以证明决策单调性。我:???

    好这么证。无非就是要证:$p<q<i$时决策$i$,$p$比$q$优,那么在决策$i-1$时$p$不可能不如$q$。

    反证之。由$p$比$q$优得到$(R_i-L_p)(R_p-L_i)>(R_i-L_q)(R_q-L_i)$,整理得$R_i(R_p-R_q)+L_i(L_p-L_q)-L_pR_p+L_qR_q>0$。在$i-1$处由$q$比$p$优同理可以得到$R_{i-1}(R_q-R_p)+L_{i-1}(L_q-L_p)+L_pR_p-L_qR_q>0$,两式相减得$(R_i-R_{i-1})(R_p-R_q)+(L_i-L_{i-1})(L_p-L_q)>0$,但这是不可能的,得证。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 //#include<set>
     5 #include<algorithm>
     6 //#include<math.h>
     7 //#include<iostream>
     8 //#include<time.h>
     9 using namespace std;
    10  
    11 #define LL long long
    12 int qread()
    13 {
    14     char c; int s=0,t=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (t=-1);
    15     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*t;
    16 }
    17  
    18 //Pay attention to read!
    19  
    20 int n;
    21 #define maxn 1000011
    22 struct QQ{int l,r,v;}qq[maxn];
    23 bool vis[maxn];
    24 bool cmpr(const QQ &a,const QQ &b) {return a.r<b.r;}
    25 LL ans;
    26 void solve(int L,int R,int ql,int qr)
    27 {
    28     if (L>R || ql>qr) return;
    29     int mid=(ql+qr)>>1;
    30     int id=mid; LL tmp=0,v;
    31     for (int i=L,to=min(mid-1,R);i<=to;i++)
    32         if ((v=(qq[mid].r-qq[i].l)*1ll*(qq[i].r-qq[mid].l))>tmp) {tmp=v; id=i;}
    33     ans=max(ans,tmp);
    34     solve(L,id,ql,mid-1); solve(id,R,mid+1,qr);
    35 }
    36  
    37 int sta[maxn],top=0;
    38 int main()
    39 {
    40     n=qread();
    41     for (int i=1;i<=n;i++) {qq[i].l=qread(); qq[i].r=qread(); qq[i].v=qq[i].r-qq[i].l;}
    42     sort(qq+1,qq+1+n,cmpr);
    43      
    44     ans=0;
    45     sta[++top]=1;
    46     for (int i=2;i<=n;i++)
    47     {
    48         int last=0;
    49         while (top && qq[sta[top]].l>=qq[i].l)
    50             last=sta[top],vis[last]=1,ans=max(ans,qq[i].v*1ll*qq[last].v),top--;
    51         sta[++top]=i;
    52     }
    53      
    54     int nn=0;
    55     for (int i=1;i<=n;i++) if (!vis[i]) qq[++nn]=qq[i]; n=nn;
    56     solve(1,n,1,n);
    57      
    58     printf("%lld
    ",ans);
    59     return 0;
    60 }
    View Code
  • 相关阅读:
    WPF DataGrid
    邮箱格式验证
    Spring Cloud微服务学习笔记
    你必须知道的MySQL知识点
    你必须掌握的分布式事务知识点
    重试操作下如何实现幂等?
    你必须掌握的关于JVM知识点
    RocketMQ开发者指南
    二分查找解题套路框架
    回溯算法解题套路框架
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9076631.html
Copyright © 2011-2022 走看看