zoukankan      html  css  js  c++  java
  • bzoj 3126: [Usaco2013 Open]Photo——单调队列优化dp

    Description

     给你一个n长度的数轴和m个区间,每个区间里有且仅有一个点,问能有多少个点

    Input

     * Line 1: Two integers N and M.

    * Lines 2..M+1: Line i+1 contains a_i and b_i.

    Output

    * Line 1: The maximum possible number of spotted cows on FJ's farm, or -1 if there is no possible solution.

    Sample Input

    5 3
    1 4
    2 5
    3 4

    INPUT DETAILS: There are 5 cows and 3 photos. The first photo contains cows 1 through 4, etc.

    Sample Output

    1
    OUTPUT DETAILS: From the last photo, we know that either cow 3 or cow 4 must be spotted.
    By choosing either of these, we satisfy the first two photos as well.
    ——————————————————————————————————
    我们用f[i]表示选i这个位置放置特殊点的最优解
    那么我们发现每个点可以选择的范围是一个区间
    并且容易证明这个区间是随着位置的增加而右移也就是单调递增的
    因为你选择了这个点 那么包含这个点的所有区间都不能再加点了
    所以r【i】=min(包含i的区间的左端点-1)
    因为每个区间都要有点所以l【i】=完整在i左边的区间中左端点的max
    这样我们就得到了每个点的转移区间
    这样完美符合单调队列的性质 所以就可以写了
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using std::min;
    using std::max;
    const int M=250007,inf=0x3f3f3f3f;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,m,x,y;
    int l[M],r[M],f[M];
    int q[M],ql=1,qr;
    int main(){
        n=read(); m=read();
        for(int i=1;i<=n+1;i++) r[i]=i-1;
        for(int i=1;i<=m;i++){
            x=read(); y=read();
            r[y]=min(r[y],x-1);
            l[y+1]=max(l[y+1],x);
        }
        for(int i=n;i;i--) r[i]=min(r[i],r[i+1]);
        for(int i=2;i<=n+1;i++) l[i]=max(l[i],l[i-1]);
        f[qr=1]=0;
        for(int i=1;i<=n+1;i++){
            for(int k=r[i-1]+1;k<=r[i];k++){
                while(ql<=qr&&f[q[qr]]<=f[k]) qr--;
                q[++qr]=k;
            }
            while(ql<=qr&&q[ql]<l[i]) ql++;
            if(ql>qr) f[i]=-inf;
            else f[i]=f[q[ql]]+1;
        }
        if(f[n+1]>=0) printf("%d
    ",f[n+1]-1);
        else printf("-1
    ");
        return 0;
    }
    View Code
  • 相关阅读:
    ES6 解构
    flutter
    selenium
    selenium
    python
    selenium
    selenium
    selenium
    selenium
    selenium- SMTP发送邮件
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7566740.html
Copyright © 2011-2022 走看看