zoukankan      html  css  js  c++  java
  • [Luogu2600]合并神犇(dp,贪心)

    [Luogu2600]合并神犇

    题目背景

    loidc来到了NOI的赛场上,他在那里看到了好多神犇。

    题目描述

    神犇们现在正排成一排在刷题。每个神犇都有一个能力值p[i]。loidc认为坐在附近的金牌爷能力参差不齐非常难受。于是loidc便想方设法对神犇们进行人道主义合并。

    loidc想把神犇的能力值排列成从左到右单调不减。他每次可以选择一个神犇,把他合并到两侧相邻的神犇上。合并后的新神犇能力值是以前两位犇的能力值之和。每次合并完成后,被合并的两个神犇就会消失。合并后的新神犇不能再分开(万一他俩有女朋友咋办)因此每次合并后神犇的总数会减1.

    loidc想知道,想治好他的强迫症需要合并多少次

    输入输出格式

    输入格式:

    第一行一个整数 n。

    第二行 n 个整数,第 i 个整数表示 p[i]。

    输出格式:

    loidc需要合并的次数

    输入输出样例

    输入样例#1:

    8
    1 9 9 4 1 2 2 9

    输出样例#1:

    3

    说明

    对于 50%的数据,0< n <=5000。

    对于 100%的数据,0< n <=200000,0< p[i] <=2147483647,p 均为随机生成。

    乍一眼看题很容易错想成贪心,将序列一直合并到当前满足条件。
    但是我们考虑这样一组数据4 1 3 2 6.....
    如果按照我们贪心的思想,合并后的序列会变成4 4 8
    但实际上我们考虑序列4 6 6 同样可以从原序列用一样的步骤合并来,而6<8,显然对于后面序列的影响更小。
    所以这个贪心是错误的。
    想到dp,用(dp[i])表示合并到(i)需用的最小次数,因为从前面的状态状态转移过来,而数据不满足我们用(O(n^2))做,由前面的错误贪心我们可以得知,我们要合并到比下一个数小,这样我们对后面的影响就更小,所以我们直接找到第一个可以更新当前状态的决策来更新即可。
    最坏的时间复杂度到了(O(n^2)),但是数据比较水(手动滑稽),于是就顺利的A了
    记得long long

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define lll long long
    lll read()
    {
    	int x=0,w=1;char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return x*w;
    }
    lll a[200010],dp[200010],f[200010],sum[200010];
    int main()
    {
    	lll n=read();
    	for(lll i=1;i<=n;i++)
    	{
    		a[i]=read();
    		sum[i]=sum[i-1]+a[i];
    	}
    	for(lll i=1;i<=n;i++)
    	{
    		lll j;
    		for(j=i-1;j>=0;j--)
    		if(sum[i]-sum[j]>=f[j]) break;
    		dp[i]=dp[j]+i-j-1;
    		f[i]=sum[i]-sum[j];
    	}
    	cout<<dp[n];
    }
    
  • 相关阅读:
    网站名记录
    Unity 之 图片显示的真实大小
    Unity 之 Time
    数据库死锁分析与解决
    使用命令远程注销服务器
    Web自动化测试框架改进
    Tomcat 性能监控及调优
    移动互联网安全性测试技术简介
    白盒测试中如何实现真正意义上并发测试(Java)
    接口性能测试方案 白皮书 V1.0
  • 原文地址:https://www.cnblogs.com/lsgjcya/p/9143458.html
Copyright © 2011-2022 走看看