yiyi049 @ 2023-10-08 14:03:31
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 4e6+114;
int n,q,a[N];
struct tree{int l,r,k,ans,tag1,tag2;}rt[N];
void build(int l,int r,int k){
rt[k].tag1=1e9+1;
rt[k].l=l,rt[k].r=r;
if(l==r){rt[k].ans=a[l],rt[k].tag2=0;return;}
int mid = (l + r) >> 1;
build(l,mid,k<<1);build(mid+1,r,k<<1|1);
rt[k].ans=max(rt[k<<1].ans,rt[k<<1|1].ans);
}
void pushdown(int k){
if(rt[k].tag1 != 1e9+1){
rt[k<<1].tag1 = rt[k<<1|1].tag1 = rt[k].tag1;
rt[k<<1].ans = rt[k<<1|1].ans = rt[k].ans;
rt[k].tag1 = 1e9+1;
rt[k].tag2 = 0;
}
if(rt[k].tag2){
rt[k<<1].tag2 += rt[k].tag2;
rt[k<<1|1].tag2 += rt[k].tag2;
rt[k<<1].ans += rt[k].tag2;
rt[k<<1|1].ans += rt[k].tag2;
rt[k].tag2 = 0;
}
}
//8 3
void updata1(int l,int r,int k,int val){
if(l <= rt[k].l && rt[k].r <= r){
rt[k].tag2 = 0;
rt[k].ans = val;
rt[k].tag1 = val;
return;
}
pushdown(k);
if(r >= rt[k<<1|1].l)updata1(l,r,k<<1|1,val);
if(l <= rt[k<<1].r)updata1(l,r,k<<1,val);
rt[k].ans=max(rt[k<<1].ans,rt[k<<1|1].ans);
}
void updata2(int l,int r,int k,int val){
if(l <= rt[k].l && rt[k].r <= r){
rt[k].tag2 += val;
rt[k].ans += val;
return;
}
pushdown(k);
if(r >= rt[k<<1|1].l)updata2(l,r,k<<1|1,val);
if(l <= rt[k<<1].r)updata2(l,r,k<<1,val);
rt[k].ans=max(rt[k<<1].ans,rt[k<<1|1].ans);
}
int query(int l,int r,int k){
if(l <= rt[k].l && rt[k].r <= r)
return rt[k].ans;
int aans = -1e9-1;
pushdown(k);
if(r >= rt[k<<1|1].l)aans = max(aans,query(l,r,k<<1|1));
if(l <= rt[k<<1].r)aans = max(aans,query(l,r,k<<1));
rt[k].ans=max(rt[k<<1].ans,rt[k<<1|1].ans);
return aans;
}
signed main(){
cin >> n >> q;
for(int i = 1;i <= n; i++)
cin >> a[i];
build(1,n,1);
while(q--){
int opt,l,r;
cin >> opt >> l >> r;
if(opt == 1){
int val;
cin >> val;
updata1(l,r,1,val);
}
if(opt == 2){
int val;
cin >> val;
updata2(l,r,1,val);
}
if(opt == 3){
cout << query(l,r,1) << "\n";
}
}
return 0;
}
by Endline @ 2023-10-08 14:39:53
虽然跟正确性无关,但是我还是要说一句:
int query(int l,int r,int k){
if(l <= rt[k].l && rt[k].r <= r)
return rt[k].ans;
int aans = -1e9-1;
pushdown(k);
if(r >= rt[k<<1|1].l)aans = max(aans,query(l,r,k<<1|1));
if(l <= rt[k<<1].r)aans = max(aans,query(l,r,k<<1));
rt[k].ans=max(rt[k<<1].ans,rt[k<<1|1].ans);
return aans;
}
查询又没有修改,为什么要 pushup
呢?
by ZBH_123 @ 2023-10-08 15:13:03
在 pushdown 函数中,如果 rt[k].tag1
和 rt[k].tag2
同时有过标记,那就应该先下传 tag1
,再下传 tag2
,而不是在 tag1
下传后就把 tag2
清零。
by ZBH_123 @ 2023-10-08 15:14:35
原因是:如果先进行修改操作,再进行增加操作,这时整个区间的最大值就是修改的值加上增加的值。
by Kevinx @ 2023-10-08 15:23:57
1e6的输入,建议使用scanf
by yiyi049 @ 2023-10-09 13:08:07
@Endline 我也很奇怪,删了分就更低了
by yiyi049 @ 2023-10-09 13:11:29
@seasons_turn 如果一个区间被修改了,那他之前的add标记也无效了,清0好像没什么问题。你说的是应该要在添加add标记的时候把修改的标记下传,不过好像还是不行。 题目说60%数据没有修改操作,我是50分,所以应该是还有别的地方写挂了。 我慢慢看吧,感谢你的回复
by ZBH_123 @ 2023-10-09 17:05:28
@yiyi049 updata1
、updata2
和 query
都存在一个问题。你写的是这样的:
if(r >= rt[k<<1|1].l)updata1(l,r,k<<1|1,val);
if(l <= rt[k<<1].r)updata1(l,r,k<<1,val);
这样就会出现一个问题:修改子树时,要修改的区间却没有变,这就可能导致区间修改到其他的区域。建议改成这种写法:
int mid=(rt[k].l+rt[k].r)>>1;
if(r<=mid){
updata1(l,r,k<<1,val);
}
else if(l>mid){
updata1(l,r,k<<1|1,val);
}
else{
updata1(l,mid,k<<1,val);
updata1(mid+1,r,k<<1|1,val);
}