zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    算法训练 表达式计算
    基础练习 十六进制转十进制
    基础练习 十六进制转十进制
    基础练习 十六进制转十进制
    New ways to verify that Multipath TCP works through your network
    TCP的拥塞控制 (Tahoe Reno NewReno SACK)
    Multipath TCP Port for Android 4.1.2
    How to enable ping response in windows 7?
    NS3
    Multipath TCP Port for Android
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5261657.html
Copyright © 2011-2022 走看看