1 条题解
-
0
自动搬运
来自洛谷,原作者为

chenzefan
蒟蒻一枚||六年级||五级钩||GESP七级搬运于
2025-08-24 23:14:07,当前版本为作者最后更新于2025-04-21 21:20:54,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
前言
本人在比赛时没有想到这题要用线段树,连暴力都没打,就宣告退出了
(主要是比较懒),现在细细想来,才发现我有多愚蠢。本题涉及知识
线段树模板,没什么多说的,不懂的点这里。
思路分析
如果已经明白的大佬,可以自行跳过。
看了题目后,发现 随着 的增,始终单调不降,所以我们只需要知道 的最小值 是多少即可解决问题。
要让 的位置的值尽可能小,我们就要用两个线段树分别维护 和 ,于是就有了下面的代码。
线段树做法,时间复杂度 。
注意:本题要开
long long。代码部分(内含注释)
蒟蒻马蜂丑陋,大佬勿喷。#include<bits/stdc++.h> using namespace std; #define int long long //以下的 p<<1 是 p*2 ,表示左孩子; p<<1|1 是 p*2+1 ,表示右孩子; const int N=5e5+5;//题目给的空间 int n,q,a[N]; struct node{ int l,r,lazy,minn; }tree1[4*N],tree2[4*N];//正常开*4的空间~ void pushdown1(int p){//处理 tree1 if(tree1[p].lazy==0) return ; tree1[p<<1].lazy+=tree1[p].lazy; tree1[p<<1|1].lazy+=tree1[p].lazy; tree1[p<<1].minn+=tree1[p].lazy; tree1[p<<1|1].minn+=tree1[p].lazy; tree1[p].lazy=0; } void pushdown2(int p){//处理 tree2 if(tree2[p].lazy==0) return ; tree2[p<<1].lazy+=tree2[p].lazy; tree2[p<<1|1].lazy+=tree2[p].lazy; tree2[p<<1].minn+=tree2[p].lazy; tree2[p<<1|1].minn+=tree2[p].lazy; tree2[p].lazy=0; } void build1(int p,int l,int r){//处理 tree1 tree1[p]={l,r,0,a[l]};//初始化 if(l==r) return ; int mid=l+r>>1; //二分建树 build1(p<<1,l,mid);build1(p<<1|1,mid+1,r); tree1[p].minn=min(tree1[p<<1].minn,tree1[p<<1|1].minn);//更新 p 节点的信息 minn } void build2(int p,int l,int r){//处理 tree2 tree2[p]={l,r,0,a[l]-l+1};//初始化 if(l==r) return ; int mid=l+r>>1; //二分建树 build2(p<<1,l,mid);build2(p<<1|1,mid+1,r); tree2[p].minn=min(tree2[p<<1].minn,tree2[p<<1|1].minn);//更新 p 节点的信息 minn } void update1(int p,int x,int y,int k){//处理 tree1 int l=tree1[p].l; int r=tree1[p].r; if(x<=l&&r<=y){ tree1[p].lazy+=k; tree1[p].minn+=k; return ; }pushdown1(p);//处理懒标记 int mid=l+r>>1; if(x<=mid) update1(p<<1,x,y,k); if(y>mid) update1(p<<1|1,x,y,k); tree1[p].minn=min(tree1[p<<1].minn,tree1[p<<1|1].minn);//更新 p 节点的信息 minn } void update2(int p,int x,int y,int k){//处理 tree2 int l=tree2[p].l; int r=tree2[p].r; if(x<=l&&r<=y){ tree2[p].lazy+=k; tree2[p].minn+=k; return ; }pushdown2(p);//处理懒标记 int mid=l+r>>1; if(x<=mid) update2(p<<1,x,y,k); if(y>mid) update2(p<<1|1,x,y,k); tree2[p].minn=min(tree2[p<<1].minn,tree2[p<<1|1].minn);//更新 p 节点的信息 minn } signed main(){ scanf("%lld%lld",&n,&q); for(int i=1;i<=n;i++) scanf("%lld",a+i); //经典建树函数 build1(1,1,n);build2(1,1,n); while(q--){ int l,r,v; scanf("%lld%lld%lld",&l,&r,&v); //经典更新函数 update1(1,l,r,v);update2(1,l,r,v); printf("%lld\n",tree1[1].minn-max(tree2[1].minn,0ll)+1); } return 0; }后附
不要抄袭代码!!不要直接复制!!
先清晰思路,再进行借鉴!!
若有笔误,请指出,感谢。
- 1
信息
- ID
- 10609
- 时间
- 1500ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者