zoukankan      html  css  js  c++  java
  • 单调队列 bzoj3126 [Usaco2013 Open]Photo

    传送门,貌似是权限题,然而我是OwO

    如果我们处理每一个点,那这个点可以从前一段能转移的地方转移过来。
    因为每个区间只有一个,所以上一个必须是从之前自己不属于的区间转移过来。也就是左侧所有右端点没到自己的区间左端点的最小值(再小就不保证这些区间里定有一个点了),最右就是所有右端点在自己右边的区间左端点的最小值(一个区间最多有一个)。然后单调队列推入点,找到符合左右区间要求的最大值(套路)即可。最后答案只要枚举到n+1,而n+1的转移范围是1~n,即可找到最大值。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define N 100005
    using namespace std;
    struct node{int l,r;}a[N];
    int n,m,L[N*2],R[N*2],f[N*2],h,t,q[N*2];
    inline bool cmp(node x,node y){return x.r<y.r;}
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)scanf("%d%d",&a[i].l,&a[i].r);
        sort(a+1,a+m+1,cmp);
        int l=0;
        for(int i=1,j=1;i<=n;i++)
        {
            while(j<=m&&a[j].r<i)l=max(l,a[j].l),j++;
            L[i]=l;
        }
        L[n+1]=1;
        l=n;
        for(int i=n,j=m;i>=1;i--)
        {
            while(a[j].r>=i&&j)l=min(l,a[j].l-1),j--;
            R[i]=l;
        }
        R[n+1]=n;
        for(int i=1,j=0;i<=n+1;i++)
        {
            for(;j<=R[i]&&j<i;j++)
            {
                if(f[j]==-1)continue;
                while(h<=t&&f[j]>f[q[t]])t--;
                q[++t]=j;
            }
            while(h<=t&&q[h]<L[i])h++;
            if(h<=t)f[i]=f[q[h]]+(i!=n+1);
            else f[i]=-1;
        }
        cout<<f[n+1];
    }
  • 相关阅读:
    SVN服务器搭建和使用(三)
    SVN服务器搭建和使用(二)
    SVN服务器搭建和使用(一)
    mysql和oracle分页
    Windows许可证 即将过期
    Java 设计模式学习笔记1——策略模式(Duck例子)
    java 抽象类与接口
    java servlet练习测试
    windows 添加开始菜单
    visio连接线设置
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632660.html
Copyright © 2011-2022 走看看