zoukankan      html  css  js  c++  java
  • bzoj 3594: [Scoi2014]方伯伯的玉米田

    3594: [Scoi2014]方伯伯的玉米田

    Time Limit: 60 Sec  Memory Limit: 128 MB
    Submit: 1399  Solved: 627
    [Submit][Status][Discuss]

    Description

    方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美。
    这排玉米一共有N株,它们的高度参差不齐。
    方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列。
    方伯伯可以选择一个区间,把这个区间的玉米全部拔高1单位高度,他可以进行最多K次这样的操作。拔玉米则可以随意选择一个集合的玉米拔掉。
    问能最多剩多少株玉米,来构成一排美丽的玉米。

    Input

    第1行包含2个整数n,K,分别表示这排玉米的数目以及最多可进行多少次操作。
    第2行包含n个整数,第i个数表示这排玉米,从左到右第i株玉米的高度ai。

    Output

    输出1个整数,最多剩下的玉米数。

    Sample Input

    3 1

    2 1 3

    Sample Output

    3

    HINT

    1 < N < 10000,1 < K ≤ 500,1 ≤ ai ≤5000

           从贪心的角度,显然有从i到n整体提高要比i到某个r提高优。因为当提高范围为r(r!=n)时,无非两种情况一种是在[r+1,n]存在一个庄稼原来比(I,r]中的某一个使得在r以前长度最大值的点大于或等于,另一种是没有更大的。那么对于第二种对于答案没有贡献,我们从i到n拔高也就没影响,而当出现第一种时,可能由于多次拔高使得原本可以在[r+1,n]之间可以有贡献的点失败了,那么显然没有从i到n拔高更优。

           不优化的姿势呢显然。

           F[i][j]表示第i个位置时(必须使用第i个位置)使用了j次技能的最大长度。所以F[i][j]=max(F[x][y])(x<i,y<j,a[x]<=a[i]+y-j) ===>(x<i,y<j,a[x]+y<=a[i]+j)。显然对于每次添加,都是现在已有状态都是满足x<i。现在我们可以将y与a[x]+y搞成树状数组,每次添加都是在左下角矩形中选一个最大值。然后这两维就可以优化为log2(n)*log2(m+max(a[i]));

    总时间复杂度就是O(n*k* log2(n)*log2(m+max(a[i])))。恩,反正过了=-=。

     1 #include<cstdio>
     2 #include<iostream>
     3 #define lowbit(x) (x&(-x))
     4 using namespace std;
     5 const int N=10050;
     6 int n,m,mx;
     7 int a[N];
     8 int c[N][550];
     9 void add(int x,int y,int w){
    10     for(int i=x;i<=mx;i+=lowbit(i))
    11         for(int j=y;j<=m+1;j+=lowbit(j))
    12             c[i][j]=max(w,c[i][j]);
    13 }
    14 inline int sum(int x,int y){
    15     int ans=0;
    16     for(int i=x;i;i-=lowbit(i))
    17         for(int j=y;j;j-=lowbit(j))
    18             ans=max(ans,c[i][j]);
    19     return ans;
    20 }
    21 int f[N][550];
    22 int main(){
    23     scanf("%d%d",&n,&m);
    24     for(int i=1;i<=n;i++){scanf("%d",a+i);mx=a[i]>mx?a[i]:mx;}
    25     mx+=m;
    26     int ans=0;
    27     for(int i=1;i<=n;i++){
    28         for(int j=m;j>=0;j--){
    29             f[i][j]=sum(a[i]+j,j+1)+1;
    30           //  printf("f[%d][%d]=%d
    ",i,j,f[i][j]);
    31             add(a[i]+j,j+1,f[i][j]);
    32             ans=max(ans,f[i][j]);
    33         }
    34     }
    35     printf("%d",ans);
    36 }
    37 /*
    38 3 1
    39 2 1 3
    40 */
  • 相关阅读:
    [BFS]luogu P2536 [AHOI2005]病毒检测
    AtCoder Regular Contest 116 总结
    NOI online 2021 #1 总结
    博客半复活
    vue2 Bus兄弟组件间传值问题:重复触发和首次未触发
    ant design中table组件的filter,如何在外部控制
    ant design vue 日期排序
    什么是断点续传?前端如何实现文件的断点续传
    主vue前端面试题补充
    P4248 [AHOI2013]差异 题解
  • 原文地址:https://www.cnblogs.com/Troywar/p/7234206.html
Copyright © 2011-2022 走看看