zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    }
    
    
  • 相关阅读:
    dotnet core 获取 MacAddress 地址方法
    dotnet core 获取 MacAddress 地址方法
    dotnet core 发布只带必要的依赖文件
    dotnet core 发布只带必要的依赖文件
    Developing Universal Windows Apps 开发UWA应用 问答
    Developing Universal Windows Apps 开发UWA应用 问答
    cmd 如何跨驱动器移动文件夹
    cmd 如何跨驱动器移动文件夹
    C++ 驱动开发 error LNK2019
    C++ 驱动开发 error LNK2019
  • 原文地址:https://www.cnblogs.com/suika/p/9240225.html
Copyright © 2011-2022 走看看