zoukankan      html  css  js  c++  java
  • BZOJ 3126 [USACO2013 Open]Photo (单调队列优化DP)

    洛谷传送门

    题目大意:给你一个长度为$n$的序列和$m$个区间,每个区间内有且仅有一个1,其它数必须是0,求整个序列中数字1最多的数量

    神题,竟然是$DP$

    定义$f_{i}$表示第i位放一个1时,最多的1的数量

    因为每个区间至少一个点,如果要在$i$位置放一个1,显然在$i$左侧没覆盖$i$的区间中,选择一个位置$j$,$j$必须保证如果在$j$放一个1,那么它右侧没有空区间再需要放1,显然$j$是没覆盖i的区间中最大的左端点,维护一个数组$l_{i}$,表示最左端能转移的区间

    因为每个区间至多一个点,如果要在$i$位置放一个1,显然在$i$左侧覆盖了$i$的区间中,选择一个位置$j$,$j$必须保证和$i$不处于任何一个相同的区间内,显然$j$是覆盖了$i$的所有区间中最小的左端点-1,维护一个数组$r_{i}$,表示最右端能转移的区间

    $f_{i}=max{f_{j},jin[l_{i},r_{i}]}$

    发现$l_{i}$和$r_{i}$都具有单调递增的性质,用单调队列优化即可,当然也可以用线段树

    细节比较多,建议不要看代码自己思考

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define N1 200100
     5 #define ll long long 
     6 #define inf 0x3f3f3f3f
     7 using namespace std;
     8 
     9 int gint()
    10 {
    11     int ret=0,fh=1;char c=getchar();
    12     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    13     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    14     return ret*fh;
    15 }
    16 int n,m;
    17 int f[N1],l[N1],r[N1];
    18 int que[N1];
    19 struct node{int l,r;}a[N1];
    20 int cmp1(node s1,node s2){
    21     if(s1.r!=s2.r) return s1.r<s2.r;
    22     else return s1.l>s2.l;}
    23 int cmp2(node s1,node s2){
    24     if(s1.r!=s2.r) return s1.r>s2.r;
    25     else return s1.l<s2.l;}
    26 
    27 
    28 int main()
    29 {
    30     scanf("%d%d",&n,&m);
    31     for(int i=1;i<=m;i++)
    32         a[i].l=gint(),a[i].r=gint();
    33     sort(a+1,a+m+1,cmp2);
    34     int k=1,mi=n+1;
    35     for(int i=n+1;i>=1;i--){
    36         while(k<=m){
    37             if(a[k].r>=i) 
    38                 mi=min(mi,a[k].l),k++;
    39             else break;}
    40         if(i<=mi) mi=i;
    41         r[i]=mi-1;
    42     }
    43     sort(a+1,a+m+1,cmp1);
    44     int ma=0;k=1;
    45     for(int i=1;i<=n+1;i++){
    46         while(k<=m){
    47             if(a[k].r<i) 
    48                 ma=max(ma,a[k].l),k++;
    49             else break;}
    50         l[i]=ma;
    51     }
    52     int hd=1,tl=0,j=0,ans=-1;
    53     for(int i=1;i<=n;i++){
    54         if(l[i]>r[i]){f[i]=-inf;continue;}
    55         while(j<=r[i]&&j<=n){
    56             while(hd<=tl&&f[j]>=f[que[tl]])
    57                 tl--;
    58             que[++tl]=j,j++;}
    59         while(hd<=tl&&que[hd]<l[i])
    60             hd++;
    61         f[i]=(hd<=tl)?(f[que[hd]]+1):1;
    62     }
    63     for(int i=l[n+1];i<=r[n+1];i++)
    64         ans=max(ans,f[i]);
    65     printf("%d
    ",ans);
    66     return 0;
    67 }
  • 相关阅读:
    Hadoop-2.4.0中HDFS文件块大小默认为128M
    看两种截然不同的设计理念:分布式文件系统支持大和小文件的思考
    SecondaryNameNode中的“Inconsistent checkpoint fields”错误原因
    查看HDFS集群信息
    执行“hdfs dfs -ls”时报ConnectException
    启动Hadoop HDFS时的“Incompatible clusterIDs”错误原因分析
    “hdfs dfs -ls”命令的使用
    SuSE Linux上修改主机名
    strerror线程安全分析
    两个SSH2间免密码登录
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10046419.html
Copyright © 2011-2022 走看看