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 ;
    }
    
  • 相关阅读:
    C# RSA
    C# DES
    C# AES 加密
    【数据结构与算法分析(c语言)】 链表的游标实现 .h文件方法全实现
    ubuntu 14.04和16.04 解决 sql 导入中文乱码问题
    React Native 错误:A problem occurred configuring project ':app'. 和Execution failed for task ‘XXX’
    React Native与夜神模拟器连接第一次白屏没有显示Welcome to React Native
    吴恩达【深度学习工程师】 04.卷积神经网络 第三周目标检测 (2)YOLO算法
    吴恩达【深度学习工程师】 04.卷积神经网络 第三周目标检测 (1)基本的对象检测算法
    吴恩达【深度学习工程师】 04.卷积神经网络 第四周特殊应用(2)神经风格转换
  • 原文地址:https://www.cnblogs.com/beretty/p/9790067.html
Copyright © 2011-2022 走看看