• bzoj2687: 交与并


    Description

        对于一个区间集合{A1,A2……AK}(K>1,Ai<>Aj{i<>j}),我们定义其权值
               W=|A1∪A2∪……∪AK|*|A1∩A2∩……AK|

         当然,如果这些区间没有交集则权值为0。

    Input

        给你N个各不相同的区间,请你从中找出若干个区间使其权值最大。

     

     第一行N

     接下来N行 l r(1<=l<r<=10^6)

    Output

        最大权值

    Sample Input

    4

    1 6

    4 8

    2 7

    3 5


    Sample Output

    24


    样例注释:选择第1个和第3个区间,交为(2,6),并为(1,7),
    权值为4*6=24.

    HINT

    100%  1<N<=10^6

    题解:

    选出的最优区间集合满足下列性质:

    1.交集肯定不能为空。

    2.设这个区间集合的并集为U,对于任意一个区间,设这个区间集合去掉这个区间的并集为U',满足U'⫋U。

    第一条显然。。。

    第二条:假如去掉这个集合后并集没有减小,去掉后显然交集不会减小,所以答案也不会变小。

    所以选出来的集合只有一个区间或两个互不包含的区间。

    由于集合大小不能为1,所以只能选两个区间。

    首先我们将区间按左端点从小到大,如果左端点相同,则按右端点从大到小的顺序排好序。

    对于其中一个区间含于另一个区间的情况:显然包含它的区间只能在他前面,而且具有单调性,所以用个单调队列维护一下即可。

    对于两个互不包含的区间的情况:先将含于其他区间的区间去掉,这时区间的左右端点都单调上升,然后有一个性质:

    假如第i-1个区间选择的最优区间为第k个(k<i-1),第i个区间选择的最优区间为第j个(j<i),则有k<=j

    证明:

    假设j<k,对于i,有:

     

    同理,对于i-1(记作i'),有:

    所以假设不成立,所以有k<=j,这样就有决策单调性了,用栈来维护一下即可。

    code:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 char ch;
     8 bool ok;
     9 void read(int &x){
    10     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    11     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    12     if (ok) x=-x;
    13 }
    14 const int maxn=1000005;
    15 typedef long long int64;
    16 int n,cnt,last;
    17 int64 ans;
    18 struct Seg{
    19     int l,r;
    20 }seg[maxn];
    21 inline bool cmp(const Seg &a,const Seg &b){return (a.l<b.l)||(a.l==b.l&&a.r>b.r);}
    22 inline int64 calc(const Seg &j,const Seg &i){return 1LL*(i.r-j.l)*(j.r-i.l);}
    23 struct Stack{
    24     int top,pos;
    25     struct Data{
    26         int l,r,id;
    27     }s[maxn],tmp;
    28     void init(){s[top=1]=(Data){2,n,1},pos=1;}
    29     bool cmp(int a,int x,int y){return calc(seg[x],seg[a])<calc(seg[y],seg[a]);}
    30     int get(int id){
    31         int l=tmp.l,r=tmp.r,m,a=tmp.id;
    32         while (l<r){
    33             m=((l+r)>>1)+1;
    34             if (cmp(m,a,id)) l=m; else r=m-1;
    35         }
    36         return l;
    37     }
    38     void push(int id){
    39         while (top&&!cmp(s[top].l,s[top].id,id)) top--;
    40         tmp=s[top--];
    41         int m=get(id);
    42         if (tmp.l<=m) s[++top]=(Data){tmp.l,m,tmp.id};
    43         if (m<n) s[++top]=(Data){m+1,n,id};
    44     }
    45     int64 query(int x){
    46         while (x>s[pos].r) pos++;
    47         return calc(seg[s[pos].id],seg[x]);
    48     }
    49 }stack;
    50 struct Que{
    51     int head,tail;
    52     struct Data{
    53         int r,len;
    54     }q[maxn],tmp;
    55     void init(){head=1,tail=0;}
    56     void push(int id){
    57         tmp=(Data){seg[id].r,seg[id].r-seg[id].l};
    58         while (head<=tail&&q[tail].len<=tmp.len) tail--;
    59         q[++tail]=tmp;
    60     }
    61     int64 query(int id){
    62         int r=seg[id].r;
    63         while (head<=tail&&q[head].r<r) head++;
    64         if (head<=tail) return q[head].len;
    65         else return -1;
    66     }
    67 }que;
    68 int main(){
    69     read(n);
    70     for (int i=1;i<=n;i++) read(seg[i].l),read(seg[i].r);
    71     sort(seg+1,seg+n+1,cmp),que.init();
    72     for (int i=1;i<=n;i++)
    73         if (seg[i].r>last) last=seg[i].r,seg[++cnt]=seg[i],que.push(i);
    74         else ans=max(ans,que.query(i)*(seg[i].r-seg[i].l));
    75     n=cnt,stack.init();
    76     for (int i=2;i<=n;i++) ans=max(ans,stack.query(i)),stack.push(i);
    77     printf("%lld
    ",ans);
    78     return 0;
    79 }
  • 相关阅读:
    U盘出现大量乱码文件,并且不能彻底删除
    使用命令生成配置文件
    input只读属性readonly和disabled的区别
    将sublime添加到鼠标右键
    mysql-front导入数据失败:“在多字节的目标代码页中,没有此 Unicode 字符可以映射到的字符”
    typeof运算符
    react input 设置默认值
    时间格式转换
    去除字符串首尾空格
    ES6基础知识汇总
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5261657.html
Copyright © 2020-2023  润新知