zoukankan      html  css  js  c++  java
  • [SCOI2014]方伯伯的玉米田

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1

    3 1
    2 1 3

    输出样例#1

    3

    说明

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


    题解

    首先分析题目可以得到一个性质

    每次选择的区间一定是原序列的一个后缀

    这样就可以DP了

    f[i][j]表示前i个数操作j次的最长不降子序列

    (f[i][j] = f[k][j - (val[k]-val[i] > 0 ? val[k]-val[i] : 0)] + 1)

    然后考虑怎么优化

    我们发现这个转移类似于二维数点

    每次转移是取一个一维是权值,一维是操作次数的矩形的前缀取max

    所以可以用二维树状数组求前缀max将复杂度优化到(nmlog^2)

    保证一维是位置,一维是权值即可

    每次查询就是要找到val[j]使小于等于 (val[i] + k)(k >= j)

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int M = 6005 ;
    const int N = 505 ;
    using namespace std ;
    inline int read() {
    	char c = getchar() ; int x = 0 , w = 1 ;
    	while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
    	while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
    	return x*w ;
    }
    
    int n , m ;
    int val[M << 1] , Ans ;
    int tmax[M][N] , vmax ;
    inline int lowbit(int x) { return x & (-x) ; }
    inline void change(int v , int k , int x) {
    	for( v ; v <= vmax + m ; v += lowbit(v))
    	    for(int i = k ; i <= m + 1 ; i += lowbit(i))
    	        tmax[v][i] = max(tmax[v][i] , x) ;
    }
    inline int query(int v , int k) {
    	int temp = 0 ;
    	for( ; v ; v -= lowbit(v))
    	    for(int i = k ; i ; i -= lowbit(i))
    	        temp = max(temp , tmax[v][i]) ;
    	return temp ;
    }
    int main() {
    	n = read() ; m = read() ;
    	for(int i = 1 ; i <= n ; i ++) val[i] = read() , vmax = max(vmax , val[i]) ;
    	for(int i = 1 ; i <= n ; i ++)
    	    for(int j = m , ret ; j >= 0 ; j --) {
    	    	ret = query(val[i] + j , j + 1) + 1 ;
    	    	Ans = max(Ans , ret) ;
    	    	change(val[i] + j , j + 1 , ret) ;
    		}
    	printf("%d
    ",Ans) ;
    	return 0 ;
    }
    
  • 相关阅读:
    Binary Tree Zigzag Level Order Traversal
    Binary Tree Level Order Traversal
    Symmetric Tree
    Best Time to Buy and Sell Stock II
    Best Time to Buy and Sell Stock
    Triangle
    Populating Next Right Pointers in Each Node II
    Pascal's Triangle II
    Pascal's Triangle
    Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/beretty/p/9790067.html
Copyright © 2011-2022 走看看