• CF1012C Hills


    CF1012C Hills

    题目描述

    Welcome to Innopolis city. Throughout the whole year, Innopolis citizens suffer from everlasting city construction.

    From the window in your room, you see the sequence of n n n hills, where i i i -th of them has height a i a_i ai . The Innopolis administration wants to build some houses on the hills. However, for the sake of city appearance, a house can be only built on the hill, which is strictly higher than neighbouring hills (if they are present). For example, if the sequence of heights is 5 , 4 , 6 , 2 5,4,6,2 5,4,6,2 , then houses could be built on hills with heights 5 5 5 and 6 6 6 only.

    The Innopolis administration has an excavator, that can decrease the height of an arbitrary hill by one in one hour. The excavator can only work on one hill at a time. It is allowed to decrease hills up to zero height, or even to negative values. Increasing height of any hill is impossible. The city administration wants to build k k k houses, so there must be at least k k k hills that satisfy the condition above. What is the minimum time required to adjust the hills to achieve the administration’s plan?

    However, the exact value of k k k is not yet determined, so could you please calculate answers for all k k k in range 1 ≤ k ≤ ⌈ n 2 ⌉ 1\leq k \leq \lceil \frac n2\rceil 1k2n? Here ⌈ n 2 ⌉ \lceil \frac n2\rceil 2n denotes n n n divided by two, rounded up.

    输入格式

    第一行一个正整数 n n n

    第二行 n n n 个正整数 a i a_i ai

    输出格式

    一行 ⌈ n 2 ⌉ \left\lceil\dfrac{n}{2}\right\rceil 2n 个数,第 i i i 个数代表 k = i k=i k=i 时的答案

    样例1
    样例输入1
    5
    1 1 1 1 1
    
    • 1
    • 2
    样例输出1
    1 2 2
    
    • 1
    样例2
    样例输入2
    3
    1 2 3
    
    • 1
    • 2
    样例输出2
    0 2
    
    • 1
    样例3
    样例输入3
    5
    1 2 3 2 2
    
    • 1
    • 2
    样例输出3
    0 1 3
    
    • 1
    数据范围

    1 ≤ n ≤ 5000 1≤n≤5000 1n5000

    1 ≤ a i ≤ 100000 1≤ai≤100000 1ai100000


    题目大意

    给你 n n n个数,你一次操作可以把某一个数减一(可以减为负数),你的目标是使任意的 k k k个数严格大于它旁边的两个数(第一个数只用严格大于第二个数,第 n n n个数只用严格大于第 n − 1 n-1 n1个数),问最少需要几次操作。 k k k是不确定的,请输出 k ∈ [ 1 , ⌈ n 2 ⌉ ] k\in[1,\left\lceil\frac{n}{2}\right\rceil] k[1,2n] 时的答案。


    题解

    f i , j f_{i,j} fi,j表示前 i i i个中有 j j j个被选中,且第 i i i个被选中所需的最小时间。则状态转移式为:

    f i , j = min ⁡ ( min ⁡ k = 1 i − 2 f k , j − 1 + w i − 1 , i , f i − 2 , j − 1 + max ⁡ ( w i − 1 , i , w i , i + 1 ) ) f_{i,j}=\min(\min\limits_{k=1}^{i-2}{f_{k,j-1}+w_{i-1,i}},\quad f_{i-2,j-1}+\max(w_{i-1,i},w_{i,i+1})) fi,j=min(k=1mini2fk,j1+wi1,i,fi2,j1+max(wi1,i,wi,i+1))

    其中 w i , j w_{i,j} wi,j表示将 a i a_i ai的高度减少至 a i < a j a_iai<aj,显然 w i , j = max ⁡ ( 0 , a i − a j + 1 ) w_{i,j}=\max(0,a_i-a_j+1) wi,j=max(0,aiaj+1)。不需要预处理,用的时候直接求即可。

    当然,如果这样做,时间复杂度为 O ( n 3 ) O(n^3) O(n3),会TLE,所以我们考虑优化。

    可以发现,每次都会用到 min ⁡ k = 1 i − 2 f k , j − 1 + w i − 1 , i \min\limits_{k=1}^{i-2}{f_{k,j-1}+w_{i-1,i}} k=1mini2fk,j1+wi1,i。所以我们设 g i , j = min ⁡ k = 1 i − 2 f k , j − 1 + w i − 1 , i g_{i,j}=\min\limits_{k=1}^{i-2}{f_{k,j-1}+w_{i-1,i}} gi,j=k=1mini2fk,j1+wi1,i,每次求 f f f值时顺便更新 g g g值,最后 min ⁡ j = i n f j , i \min\limits_{j=i}^n f_{j,i} j=iminnfj,i即为选 i i i座山的答案。

    code

    #include
    using namespace std;
    int n,a[100005];
    long long ans,g[5005],f[5005][2505];
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    	}
    	for(int i=0;i<=n;i++){
    		for(int j=1;j<=(n+1)/2;j++) f[i][j]=1e18;
    		g[i]=1e18;
    	}
    	for(int i=1;i<=n;i++){
    		f[i][1]=max(0,a[i-1]-a[i]+1)+max(0,a[i+1]-a[i]+1);
    	}
    	for(int i=2;i<=n;i++){
    		for(int j=2;j<=(i+1)/2;j++){
    			f[i][j]=min(g[j-1]+max(0,a[i-1]-a[i]+1),
    			f[i-2][j-1]-max(0,a[i-1]-a[i-2]+1)+max(0,a[i-1]-min(a[i],a[i-2])+1))+max(0,a[i+1]-a[i]+1);
    		}
    		for(int j=1;j<=(i+1)/2;j++){
    			g[j]=min(g[j],f[i-2][j]);
    		}
    	}
    	for(int i=1;i<=(n+1)/2;i++){
    		ans=1e18;
    		for(int j=i;j<=n;j++) ans=min(ans,f[j][i]);
    		printf("%lld ",ans);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
  • 相关阅读:
    长沙学院2022暑假训练赛(一)
    当SSC遇见RPA:最大化发挥共享服务模式效用
    docker
    电子数据取证-流程与技术
    STM32驱动AHT10&OLED显示温湿度
    C/C++ 进程间通信system V IPC对象超详细讲解(系统性学习day9)
    网络安全面试题汇总(附答案)
    DDD基础_领域设计10大基础概念
    Spring AOP浅谈
    力扣每日一题2022-09-22简单题:能否连接形成数组
  • 原文地址:https://blog.csdn.net/tanjunming2020/article/details/127452461