codeforces 940E
题意:
给
定
含
n
个
数
的
序
列
,
将
序
列
划
分
为
若
干
段
长
度
不
等
的
子
序
列
,
记
每
段
长
度
为
k
,
给定含n个数的序列,将序列划分为若干段长度不等的子序列,记每段长度为k,
给定含n个数的序列,将序列划分为若干段长度不等的子序列,记每段长度为k,
则
每
段
子
序
列
需
要
删
除
[
k
c
]
个
最
小
元
素
。
则每段子序列需要删除[\frac kc]个最小元素。
则每段子序列需要删除[ck]个最小元素。
问
所
有
子
序
列
元
素
之
和
的
最
小
值
。
问所有子序列元素之和的最小值。
问所有子序列元素之和的最小值。
题解:
d
p
[
i
]
表
示
前
i
个
元
素
组
成
的
序
列
的
最
优
解
,
用
s
u
m
[
i
]
维
护
区
间
[
1
,
i
]
的
前
缀
和
。
dp[i]表示前i个元素组成的序列的最优解,用sum[i]维护区间[1,i]的前缀和。
dp[i]表示前i个元素组成的序列的最优解,用sum[i]维护区间[1,i]的前缀和。
最
优
方
案
为
每
段
子
序
列
长
度
不
超
过
c
。
最优方案为每段子序列长度不超过c。
最优方案为每段子序列长度不超过c。
- 母 序 列 第 i 个 元 素 是 否 与 前 c − 1 个 元 素 构 成 长 度 为 c 的 区 间 , d p [ i ] = m i n ( d p [ i − 1 ] + a [ i ] , d p [ i − c ] + s u m [ i ] − s u m [ i − c ] − m i n ( i − c + 1 , i ) ) 母序列第i个元素是否与前c-1个元素构成长度为c的区间,dp[i] = min(dp[i-1]+a[i], dp[i-c]+sum[i]-sum[i-c]-min(i−c+1,i)) 母序列第i个元素是否与前c−1个元素构成长度为c的区间,dp[i]=min(dp[i−1]+a[i],dp[i−c]+sum[i]−sum[i−c]−min(i−c+1,i))
- 维 护 c 个 元 素 的 最 小 值 , ∗ m u l . b e g i n ( ) 代 替 上 式 m i n ( i − c + 1 , i ) , 可 得 d p [ i ] = m i n ( d p [ i − 1 ] + a [ i ] , d p [ i − c ] + s u m [ i ] − s u m [ i − c ] − ∗ m u l . b e g i n ( ) ) 维护c个元素的最小值,*mul.begin()代替上式min(i−c+1,i),可得dp[i] = min(dp[i-1]+a[i], dp[i-c]+sum[i]-sum[i-c]-*mul.begin()) 维护c个元素的最小值,∗mul.begin()代替上式min(i−c+1,i),可得dp[i]=min(dp[i−1]+a[i],dp[i−c]+sum[i]−sum[i−c]−∗mul.begin())
#include <bits\stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100001;
ll a[N], sum[N];
ll dp[N];
int main() {
int n, c;
cin >> n >> c;
for(int i = 1 ; i <= n ; i++){
cin >> a[i];
dp[i] = sum[i] = sum[i-1]+a[i];
}
multiset <ll> mul;
for(int i = 1 ; i < c ; i++){
mul.insert(a[i]);
}
for(int i = c ; i <= n ; i++){
mul.insert(a[i]);
dp[i] = min(dp[i-1]+a[i], dp[i-c]+sum[i]-sum[i-c]-*mul.begin());
mul.erase(mul.find(a[i-c+1]));
}
cout << dp[n] << endl;
return 0;
}