专栏文章

题解:P12372 [蓝桥杯 2022 省 Python B] 最优清零方案

P12372题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mioy3xs0
此快照首次捕获于
2025/12/03 03:02
3 个月前
此快照最后确认于
2025/12/03 03:02
3 个月前
查看原文

蓝桥杯2022省赛PythonB组 - 最优清零方案 题解

题目描述

给定长度为 NN 的数列,每次操作可选择:
  1. 单点减 11 (操作代价1)
  2. 连续 KK 个数各减 11 (操作代价1)
求将整个数列清零的最少操作次数。

思路

因为 K1K \ge 1 所以多用操作 22 更优。
对于每个长度为 KK 的区间,都用操作 22 操作这个区间所有的数的最小值次(用线段树维护)。
最后再将操作后剩下的所有数加起来就行了。

Code

CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int a[N];
struct node{
	int ls,rs,sum,add,mx,mn;
	#define l(x) tr[x].ls
	#define r(x) tr[x].rs
	#define mn(x) tr[x].mn
	#define mx(x) tr[x].mx
	#define sum(x) tr[x].sum
	#define add(x) tr[x].add
}tr[N*4];
void build(int p,int l,int r){
	l(p)=l,r(p)=r;
	if(l==r){
		sum(p)=a[l];
		mn(p)=mx(p)=a[l];
		return; 
	} 
	int mid=l+r>>1;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	sum(p)=sum(p*2)+sum(p*2+1);
	mn(p)=min(mn(p*2),mn(p*2+1));
	mx(p)=max(mx(p*2),mx(p*2+1));
}
void spread(int p){
	if(add(p)){
		sum(p*2)+=add(p)*(r(p*2)-l(p*2)+1);
		mx(p*2)+=add(p),mn(p*2)+=add(p); 
		add(p*2)+=add(p);
		sum(p*2+1)+=add(p)*(r(p*2+1)-l(p*2+1)+1);
		mx(p*2+1)+=add(p),mn(p*2+1)+=add(p); 
		add(p*2+1)+=add(p);
		add(p)=0;
	}
}
void change(int p,int l,int r,int d){
	if(l(p)>=l && r(p)<=r){
		sum(p)+=(r(p)-l(p)+1)*d;
		add(p)+=d;
		mn(p)+=d,mx(p)+=d;
		return;
	}
	int mid=l(p)+r(p)>>1;
	spread(p);
	if(l<=mid) change(p*2,l,r,d);
	if(r>mid)  change(p*2+1,l,r,d);
	sum(p)=sum(p*2)+sum(p*2+1);
	mn(p)=min(mn(p*2),mn(p*2+1));
	mx(p)=max(mx(p*2),mx(p*2+1));
}
int ask(int p,int l,int r){
	if(l(p)>=l && r(p)<=r){
		return mn(p);
	}
	spread(p);
	int mid=l(p)+r(p)>>1;
	int ans=2e9;
	if(l<=mid) ans=min(ans,ask(p*2,l,r));
	if(r>mid)  ans=min(ans,ask(p*2+1,l,r));
	return ans;
}
int ask2(int p,int l,int r){
	if(l(p)>=l && r(p)<=r){
		return sum(p);
	}
	spread(p);
	int mid=l(p)+r(p)>>1;
	int ans=0;
	if(l<=mid) ans+=ask2(p*2,l,r);
	if(r>mid)  ans+=ask2(p*2+1,l,r);
	return ans;
}
int k,ans=0;
signed main(){
	int n,m;
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	for(int i=1;i<=n-k+1;i++){
		int maxx=ask(1,i,i+k-1);
		ans+=maxx;
		if(maxx>0) change(1,i,i+k-1,-maxx); 
	}
	ans+=ask2(1,1,n);
	cout<<ans;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...