P1438 无聊的数列 题解
背景
看到题解都是差分,竟然还有建两颗线段树和二阶差分的大佬。
我感到不理解,很不理解。
题目正解
本题正解很明显就是:线段树
是的,你没有看错,就只有线段树。
很显然我们直接按照线段树板题写就可以了,维护题目需要维护的,注意到只有单点查询,所以我们根本不需要维护区间和,对于区间来讲,我们只用维护修改操作,修改操作只需要
考虑该操作如何向下传递(pushdown):
- 对于左区间来讲,
没有改变,直接赋值。 - 对于右区间来讲,只有
,其中 是左区间长度。
此外我们发现:对于同一段区间,修改操作是可以叠加的。
好的,我们做完了,甚至不需要 pushup 操作。
是的,就是这么简单,当区间变成一个点时,我们发现对于这个点的修改就是加上
AC 代码:
#include<bits/stdc++.h>
using namespace std;
#define N 500000
#define ls rt<<1
#define rs rt<<1|1
int n,m,a[N];
struct tree{
long long l,r,w,op,k,d;
}tr[N];
void build(int rt,int l,int r){
tr[rt]={l,r,0,0,0,0};
if(l==r){
tr[rt].w=a[l];return ;
}
int mid=(l+r)>>1;
build(ls,l,mid);build(rs,mid+1,r);
}
void pushdown(int rt){
if(tr[rt].op){
tr[ls].k+=tr[rt].k;
tr[ls].d+=tr[rt].d;
tr[ls].op=1;
tr[rs].k+=tr[rt].k+(tr[rs].l-tr[ls].l)*tr[rt].d;
tr[rs].d+=tr[rt].d;
tr[rs].op=1;
}
tr[rt].op=0;
tr[rt].d=tr[rt].k=0;
}
void update(int rt,int cl,int cr,int k,int d){
int l=tr[rt].l,r=tr[rt].r;
if(cl<=l&&r<=cr){
tr[rt].op=1;
tr[rt].k+=k+(l-cl)*d;
tr[rt].d+=d;
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if(cl<=mid) update(ls,cl,cr,k,d);
if(cr>mid) update(rs,cl,cr,k,d);
}
long long query(int rt,int p){
int l=tr[rt].l,r=tr[rt].r;
// printf("|%d %d %d %d %d\n",l,r,tr[rt].d,tr[rt].k,tr[rt].w);
if(l==r){
tr[rt].w+=tr[rt].k;
tr[rt].k=0;tr[rt].d=0;
return tr[rt].w;
}
pushdown(rt);
int mid=(l+r)>>1;
if(p<=mid) return query(ls,p);
else return query(rs,p);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,1,n);
while(m--){
int t,l,r,k,d,p;
scanf("%d",&t);
if(t==1){
scanf("%d%d%d%d",&l,&r,&k,&d);
update(1,l,r,k,d);
}else{
scanf("%d",&p);
printf("%lld\n",query(1,p));
}
}
return 0;
}
不开 long long 见祖宗!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】