bzoj2687 交与并

来源:互联网 发布:射频开关矩阵设计方案 编辑:程序博客网 时间:2024/04/29 20:10

【题意】

n个不重复区间,选择>=2个区间,求交集长度*并集长度的最大值。

【数据范围】

2<=n<=10^6

【思路】

[1]对于一般情况,若A包含于B,则A舍去

排序后把所有被包含的区间均舍去

剩余区间左、右端点均单增

任意一种选取方案等价于只选取该方案中最左、最右区间

故暴力做法为枚举其中的两个区间更新答案,O(n^2)

推推式子发现决策具有单调性,故两个指针扫描一遍即可

[2]对于特殊情况,即上述方法求得答案为0

去掉的区间可能会更新答案,故删除区间的同时更新答案

【时间复杂度】

O(n)

#include<cstdio>#include<cstring>#include<algorithm>#define N 1000010#define ll long longusing namespace std;struct aa{int l, r;}a[N], b[N];int n, now, mxp, l, flag[N];ll ans;inline int read(){    int x=0, f=1; char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}    return x*f;}bool cmp(aa a, aa b){    if(a.l!=b.l)return a.l<b.l;    return a.r>b.r;}ll get(int i, int j){    if(b[i].r<b[j].l)return 0;    return (ll)(b[i].r-b[j].l+1)*(b[j].r-b[i].l+1);}int main(){    n=read();    for(int i=1; i<=n; i++){a[i].l=read(); a[i].r=read()-1;}    sort(a+1, a+1+n, cmp);    now=mxp=ans=0;    for(int i=1; i<=n; i++){        if(a[i].r<=now){            flag[i]=mxp;            ans=max(ans, (ll)(a[i].r-a[i].l+1)*(a[mxp].r-a[mxp].l+1));        }else flag[i]=0;        if(now<a[i].r){now=a[i].r; mxp=i;}    }    l=0;    for(int i=1; i<=n; i++)if(!flag[i])b[++l]=a[i];    now=2;    for(int i=1; i<=l-1; i++){        if(now==i)now++;        while(now<=l-1&&get(i, now)<get(i, now+1))now++;        ans=max(ans, get(i, now));    }    printf("%lld", ans);    return 0;}


0 0
原创粉丝点击