在线评测链接
题目描述
给定一个数组 a 1 , a 2 , a 3 , . . . , a n a_1,a_2,a_3,...,a_n a1,a2,a3,...,an , 你每次可以对数组任意一个正整数进行-1操作。问最少多少次使得其所有长度为 x x x的子数组的和 ≤ \leq ≤ y y y。
输入描述
第一行,两个整数 x , y ( 1 ≤ x ≤ 10 , 0 ≤ y ≤ 1000 ) x , y(1\leq x \leq 10,0\leq y\leq 1000) x,y(1≤x≤10,0≤y≤1000)
第二行输入一个整数 n ( 1 ≤ n ≤ 1 e 5 ) n (1 \leq n \leq 1e5) n(1≤n≤1e5),代表数组的大小。
第三行输入 n n n 个非负整数表示数组 a a a ,第 i i i 个数为 a i ( 0 ≤ a i ≤ 1 0 5 ) a_i(0 \leq a_i\leq 10^5) ai(0≤ai≤105) 。
输出描述
一个整数,代表最少操作次数。
样例
输入
2 4
4
1 3 3 3
输出
2
一种方案是最终改成:1 3 1 3 , 把第三个位置的数从3改成1。花费两次操作
输入
2 6
4
1 3 3 3
输出
0
思路:贪心
从前往后依次枚举每个长度为 m m m的区间,如果当前区间和不满足条件,按照贪心的思想考虑,则应该优先减少当前区间的最后一个元素,这样可以使得后面区间操作次数少一些。
时间复杂度
O ( n ) O(n) O(n)
代码
C++
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main (){
int m , up;
cin >> m >> up;
int n;
cin >> n;
vector<int> a(n);
for (int i = 0 ; i < n ; i++) cin >> a[i];
if (m == 0 || m > n) {
cout << 0 << endl;
return 0;
}
int sum = 0 , ans = 0;
for (int i = 0 ; i < m - 1; i++){
sum += a[i];
}
for (int i = m - 1 ; i < n ; i++){
sum += a[i];
for (int j = i ; j >= i - m + 1 ; j--){
if (sum <= up){
break;
}
if (sum - a[j] <= up){
a[j] -= sum - up;
ans += sum - up;
sum = up;
}
else {
sum -= a[j];
ans += a[j];
a[j] = 0;
}
}
sum -= a[i - m + 1];
}
cout << ans << endl;
return 0;
}
python代码
M,N = map(int, input().split())
X = int(input())
requests = [int(c) for c in input().split()]
r = M
res = 0
while(r<=X):
window = requests[r-M:r]
total_requests = sum(window)
if total_requests>N:
to_remove = total_requests - N
res += to_remove
for i in range(r-1, r-M-1, -1):
if to_remove>requests[i]:
to_remove -= requests[i]
requests[i] = 0
else:
requests[i] = requests[i] - to_remove
break
r += 1
print(res)
Java代码
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int x=sc.nextInt();
int y=sc.nextInt();
int n=sc.nextInt();
long []a=new long[n];
for(int i=0;i<n;i++){
a[i]=sc.nextInt();
}
long res=0;
for(int i=0;i<=a.length-x;i++){
long sum=0;
for(int j=i;j<i+x;j++){
sum+=a[j];
}
if(sum>y){
res+=sum-y;
long last=sum-y;
int j=i+x-1;
while(j>=i){
if(a[j]>=last){
a[j]=a[j]-last;
break;
}else{
last=last-a[j];
a[j]=0;
j--;
}
}
}
}
System.out.println(res);
}
}