BZOJ_2369_区间_决策单调性

BZOJ_2369_区间_决策单调性

Description

对于一个区间集合
{A1,A2……Ak}(K>1,Ai不等于Aj(i不等于J),定义其权值
 
S=|A1∪A2∪……AK|*|A1∩A2……∩Ak|
即它们的交区间的长度乘上它们并区间的长度。
显然,如果这些区间没有交集则权值为0。
Your Task
给定你若干互不相等的区间,选出若干区间使其权值最大。

Input

第一行n表示区间的个数
接下来n行每行两个整数l r描述一个区间[l,r]

Output

 
在一行中输出最大权值

Sample Input

4
1 6
4 8
2 7
3 5

Sample Output

24

HINT

样例解释

    选择[1,6]和[2,7]是最优的。

数据约定

100%:1<N<=10^6,1<=L<R<=10^6


 

首先有结论:肯定有一种最优方案只选了两个,因为选n个不会比只选左右的区间更优。

于是按左端点排序,然后把区间包含的那种直接统计答案并踢掉。

现在左右都单调了,可以证明满足决策单调性。

直接上决策单调性即可。

注意这道题区间长度为r-l。

 

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
__attribute__((optimize("-O3")))inline char nc() {
    static char buf[100000],*p1,*p2;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
__attribute__((optimize("-O3")))int rd() {
    int x=0; 
    char s=nc();
    while(s<'0'||s>'9') s=nc();
    while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
    return x;
}
#define N 1000050
struct Line {
    int l,r;
    bool operator < (const Line &x) const {
        return l<x.l;
    }
}a[N];
struct A {
    int l,r,p;
}Q[N];
__attribute__((optimize("-O3")))ll Y(int j,int i) {
    // if(a[j].r<a[i].l) return -1ll<<60;
    return 1ll*(a[j].r-a[i].l)*(a[i].r-a[j].l);
}
__attribute__((optimize("-O3")))int find(const A &a,int x) {
    int l=a.l,r=a.r+1;
    while(l<r) {
        int mid=(l+r)>>1;
        if(Y(a.p,mid)>=Y(x,mid)) l=mid+1;
        else r=mid;
    }
    return l;
}
ll ans;
int n;
__attribute__((optimize("-O3")))int main() {
    n=rd();
    register int i,t=0;
    for(i=1;i<=n;i++) {
        a[i].l=rd();
        a[i].r=rd();
    }
    sort(a+1,a+n+1); a[0].r=-1;
    for(i=1;i<=n;i++) {
        if(a[i].r<=a[t].r) {
            ans=max(ans,1ll*(a[t].r-a[t].l)*(a[i].r-a[i].l));
        }else a[++t]=a[i];
    }
    n=t;
    int l=0,r=0;
    Q[r++]=(A){1,n,1};
    for(i=2;i<=n;i++) {
        if(l<r) Q[l].l++;
        while(l<r&&Q[l].l>Q[l].r) l++;
        if(l<r) ans=max(ans,Y(Q[l].p,i));
        if(l==r||Y(i,n)>Y(Q[r-1].p,n)) {
            while(l<r&&Y(i,Q[r-1].l)>Y(Q[r-1].p,Q[r-1].l)) r--;
            if(l==r) Q[r++]=(A){i,n,i};
            else {
                int x=find(Q[r-1],i);
                Q[r-1].r=x-1; Q[r++]=(A){x,n,i};
            }
        }
    }
    printf("%lld\n",ans);
}

 

posted @ 2018-06-28 18:51  fcwww  阅读(301)  评论(0编辑  收藏  举报