解题思路:看注释
注意事项:
参考代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000010
#define INF 1000010
typedef long long ll;
int a[maxn];
ll ans;
struct node{
ll l,r;
ll minval,minpla;
ll sum;
ll lazy;//懒标记,表示tree[i]的所有子树都要修改(tree[i]不用修改)
}tree[maxn<<2];
void push_up(int i){
if(tree[i<<1].minval<=tree[i<<1|1].minval){
tree[i].minval=tree[i<<1].minval;
tree[i].minpla=tree[i<<1].minpla;
}
else{
tree[i].minval=tree[i<<1|1].minval;
tree[i].minpla=tree[i<<1|1].minpla;
}
tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
}
void build(int i,int l,int r){
tree[i].l=l;tree[i].r=r;tree[i].lazy=0;
if(l==r){
tree[i].minval=a[l];
tree[i].minpla=l;
tree[i].sum=a[l];
return;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
push_up(i);
}
void push_down(int i){//这个区间应该每个数减k
if(!tree[i].lazy)return;
tree[i<<1].sum-=tree[i].lazy*(tree[i<<1].r+1-tree[i<<1].l);
tree[i<<1].minval-=tree[i].lazy;
tree[i<<1|1].sum-=tree[i].lazy*(tree[i<<1|1].r+1-tree[i<<1|1].l);
tree[i<<1|1].minval-=tree[i].lazy;
tree[i<<1].lazy+=tree[i].lazy;
tree[i<<1|1].lazy+=tree[i].lazy;
tree[i].lazy=0;
}
void modify(int i,int l,int r,int k){//让区间l,r的每一个数都减去k,并更新线段树
//if(tree[i].l>r||tree[i].r<l)return;//实际上永远不会到这种情形
if(tree[i].l>=l&&tree[i].r<=r){
tree[i].lazy+=k;
tree[i].sum-=(tree[i].r-tree[i].l+1)*k;//就是这个地方,可能会超过int类型,所以我索性把结构体里所有变量定义为了long long
tree[i].minval-=k;
return;
}
push_down(i);
if(tree[i<<1].r>=l){
modify(i<<1,l,r,k);
}
if(tree[i<<1|1].l<=r){
modify(i<<1|1,l,r,k);
}
push_up(i);
}
pair<int,int> querymin(int i,int l,int r){//应该能同时返回minval和minpla
//if(tree[i].l>r||tree[i].r<l)return;//实际上永远不会到这种情形
pair<int,int> ret,tmp;
if(tree[i].l>=l&&tree[i].r<=r){
ret.first=tree[i].minval;
ret.second=tree[i].minpla;
return ret;
}
push_down(i);
ret.first=INF;tmp.first=INF;
if(tree[i<<1].r>=l){
ret=querymin(i<<1,l,r);
}
if(tree[i<<1|1].l<=r){
tmp=querymin(i<<1|1,l,r);
}
if(ret.first<=tmp.first)return ret;
else return tmp;
}
ll querysum(int i,int l,int r){
if(tree[i].l>=l&&tree[i].r<=r){
return tree[i].sum;
}
push_down(i);
ll sum=0;
if(tree[i<<1].r>=l){
sum+=querysum(i<<1,l,r);
}
if(tree[i<<1|1].l<=r){
sum+=querysum(i<<1|1,l,r);
}
return sum;
}
int main(){
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,1,n);
int l=1,r=min(n,k);
pair<int,int> x;
int minpla,minval;
while(l<=n){
if(querysum(1,l,l)==0){
l++;
r=min(n,l+k-1);
continue;
}
if(r==l+k-1){
x=querymin(1,l,r);
minval=x.first;minpla=x.second;
ans+=minval;
modify(1,l,r,minval);//[l,r]整体减minval
if(l<minpla)ans+=querysum(1,l,minpla-1);
l=minpla+1;
r=min(n,l+k-1);
}
else{
ans+=querysum(1,l,r);
break;
}
}
printf("%lld",ans);
system("pause");
return 0;
}
0.0分
2 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复