zoukankan      html  css  js  c++  java
  • bzoj2442[Usaco2011 Open]修剪草坪*

    bzoj2442[Usaco2011 Open]修剪草坪

    题意:

    从一个序列中选n个数,要求这些数中不能有超过k个数在原序列中位置是连续的。求最大的取数之和。n≤100000。

    题解:

    f[i]表示不选i,1到i-1可以得到的最大取数之和。则f[i]=max(f[j]+sum[i-1]-sum[j]),i-j≤k。j比k好当且仅当f[j]+sum[i-1]-sum[j]>f[k]+sum[i-1]-sum[k],即f[j]-sum[j]>f[k]-sum[k]。故只要用单调队列维护f[j]-sum[j]即可。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define inc(i,j,k) for(int i=j;i<=k;i++)
     5 #define maxn 100010
     6 #define ll long long
     7 using namespace std;
     8 
     9 inline int read(){
    10     char ch=getchar(); int f=1,x=0;
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    12     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    13     return f*x;
    14 }
    15 ll sm[maxn],q1[maxn],f[maxn]; int n,k,l,r,q2[maxn];
    16 int main(){
    17     n=read(); k=read(); inc(i,1,n)sm[i]=sm[i-1]+read();
    18     l=1; r=2; q1[l]=q2[l]=0; q1[r]=-sm[1]; q2[r]=1;
    19     inc(i,2,n+1){
    20         while(l<=r&&q2[l]<i-k-1)l++; f[i]=q1[l]+sm[i-1];
    21         while(l<=r&&f[i]-sm[i]>=q1[r])r--; q1[++r]=f[i]-sm[i]; q2[r]=i;
    22     }
    23     printf("%lld",f[n+1]); return 0;
    24 }

    20160912

  • 相关阅读:
    linux权限掩码
    主机跨网通信时的字节序转换
    鸽巢原理-poj3370
    鸽巢原理
    JS面向对象关键词
    Less 命令技巧,从底部网上看
    软件工程概论第七章
    软件工程概论第八章
    软件工程概论第六章
    软件工程概论第五章
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5876557.html
Copyright © 2011-2022 走看看