列表

详情


NC232855. 神奇数组

描述

你得到了一个长度为n的数组a和一个整数c

这个数组非常神奇,划分后对任意长度为k的数组,它的值为数组中除最小的个元素外其他元素的和。求将数组划分为若干个连续的子数组后,所有子数组值的和的最小值。

输入描述

第一行输入两个整数n,c ()。
第二行输入n个整数a_i (),表示a的元素。

输出描述

输出一个整数,表示和的最小值。

示例1

输入:

3 5
1 2 3

输出:

6

示例2

输入:

12 10
1 1 10 10 10 10 10 10 9 10 10 10

输出:

92

示例3

输入:

7 2
2 3 6 4 5 7 1

输出:

17

示例4

输入:

8 4
1 3 4 5 5 3 4 1

输出:

23

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 22ms, 内存消耗: 1812K, 提交时间: 2022-11-23 10:20:33

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int len,k;
ll dp[N],a[N];
deque<int> q;
int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>len>>k;
    ll s=0;
    for(int i=1;i<=len;i++) cin>>a[i],s+=a[i];
    for(int i=1;i<=len;i++){
        if(!q.empty()&&q.front()<=i-k) q.pop_front();
        while(!q.empty()&&a[i]<=a[q.back()]){
            q.pop_back();
        }
        q.push_back(i);
        dp[i]=dp[i-1];
        if(i>=k){
            dp[i]=max(dp[i],dp[i-k]+a[q.front()]);
        }
    }
    cout<<s-dp[len];
}

C++(clang++ 11.0.1) 解法, 执行用时: 39ms, 内存消耗: 1416K, 提交时间: 2022-10-12 16:52:20

#include<bits/stdc++.h>
using namespace std ;
const int N = 1e5 + 5 ;
#define ll long long
int n,c ;
int a[N],q[N] ;
ll f[N] ;
int main()
{
	cin>>n>>c ;
	ll sum=0 ;
	for(int i=1;i<=n;++i) cin>>a[i],sum+=a[i] ;
	f[0]=0 ;
	int l=1,r=0 ;
	for(int i=1;i<=n;++i)
	{
		while(l<=r&&i-q[l]>=c) l++ ;
		while(l<=r&&a[i]<=a[q[r]]) r-- ;
		q[++r]=i ;
		if(i>=c) f[i]=max(f[i-1],f[i-c]+a[q[l]]) ;
        else f[i]=f[i-1] ;
	}
	cout<<sum-f[n]<<'\n' ;
	return 0 ;
}

上一题