1 solutions
-
0
题解
呜呜呜,在不知调了多久后,终于过了......
思路
看到神奇的就知道,这题会比其他题简单很多,只 是 个 绿 题
Q:为啥调了二十多次??? A:因为我太没实力了......
一开始,我以为直接把pushup改了就行了,可是仔细一看,题目居然还需要区间修改(就是修改,不是加和)。
然后,我以为只需要再写一个函数就好了。可是突然发现,原来的懒标记只能用在加法上,不能用在修改上。所以还需要一个懒标记来专门应对修改(就是修改,不是加和)。
接着,我以为只需要再加一个懒标记就可以了。但是,仔细一看,这个数字可能是负数,所以在初始化时需要把初始值修改成一个很小的数。
然后,我以为只需要修改初始值就可以了。但是,仔细一想,突然发现如果先处理加法的懒标记再处理修改(就是修改,不是加和)的懒标记,加的数就不会加上去,而是被新的数给覆盖掉。所以,写pushdown时需要先修改(就是修改,不是加和)再加和。
再然后,我以为只需要再修改一下pushdown就好了。但是,我灵机一动,如果在修改(就是修改,不是加和)区间的时候,没有把旧的加法标记去掉,原来应该被覆盖的加法就会被加到新的数上。所以,在写修改(就是修改,不是加和)函数的时候,不仅需要修改自身的懒标记,还需要把加和的懒标记设为0。
最后,我以为我可以过了,但是突然发现,在求区间最大值的时候,max值也要初始化为一个非常小的数,不然会出现非常悲伤的事。
然后……没有然后了。
呆码
错误示范1
死因错误原因:把加和标记重置了。#include<bits/stdc++.h> #define ety -114411441144123 typedef long long ll; using namespace std; struct node{ int l; int r; ll num; }tree[10000001]; ll arr[10000001],n; ll tag1[10000001],tag2[10000001]; void createTree(ll sp,ll l,ll r){ tree[sp].l=l; tree[sp].r=r; if(l==r){ tree[sp].num=arr[l]; return; } ll mid=(l+r)>>1; createTree(sp<<1,l,mid); createTree((sp<<1)+1,mid+1,r); tree[sp].num=max(tree[sp<<1].num,tree[(sp<<1)+1].num); } void cltag2(ll sp){ tree[sp<<1].num+=tag2[sp];tree[(sp<<1)+1].num+=tag2[sp]; tag2[sp<<1]=tag2[(sp<<1)+1]=tag2[sp]; tag2[sp]=0; } void cltag1(ll sp){ if(tag1[sp]!=ety){ tree[sp<<1].num=tag1[sp];tree[(sp<<1)+1].num=tag1[sp]; tag1[sp<<1]+=tag1[sp]; tag1[(sp<<1)+1]+=tag1[sp]; tag1[sp]=ety; } } void areaChange(ll sp,ll l,ll r,ll c){ if(tree[sp].l>=l&&tree[sp].r<=r){ tag1[sp]=c; tree[sp].num=c; return; } cltag1(sp); ll mid=(tree[sp].l+tree[sp].r)>>1; if(l<=mid)areaChange(sp<<1,l,r,c); if(r>mid)areaChange((sp<<1)+1,l,r,c); tree[sp].num=max(tree[sp<<1].num,tree[(sp<<1)+1].num); } void areaAdd(ll sp,ll l,ll r,ll c){ if(tree[sp].l>=l&&tree[sp].r<=r){ tag2[sp]+=c; tree[sp].num+=c; return; } cltag2(sp); ll mid=(tree[sp].l+tree[sp].r)>>1; if(l<=mid)areaAdd(sp<<1,l,r,c); if(r>mid)areaAdd((sp<<1)+1,l,r,c); tree[sp].num=max(tree[sp<<1].num,tree[(sp<<1)+1].num); } ll areaAsk(ll sp,ll l,ll r){ if(tree[sp].l>=l&&tree[sp].r<=r)return tree[sp].num; cltag1(sp); cltag2(sp); ll maxn=0; ll mid=(tree[sp].l+tree[sp].r)>>1; if(l<=mid)maxn=max(maxn,areaAsk(sp<<1,l,r)); if(r>mid)maxn=max(maxn,areaAsk((sp<<1)+1,l,r)); return maxn; } int main(){ // freopen("in.in","r",stdin); // freopen("out.out","w",stdout); cin.tie(0);cout.tie(0); ios::sync_with_stdio(false); fill(tag1,tag1+10000000,ety); ll q; cin>>n>>q; for(ll i=1;i<=n;i++)cin>>arr[i]; createTree(1,1,n); while(q--){ int m; cin>>m; if(m==1){ ll l,r,x; cin>>l>>r>>x; areaChange(1,l,r,x); }else if(m==2){ ll l,r,x; cin>>l>>r>>x; areaAdd(1,l,r,x); }else{ ll l,r; cin>>l>>r; cout<<areaAsk(1,l,r)<<endl; } } }
错误示范2
死因错误原因:初始值没有改,计算时的初始值也没有改。 更正了:加和标记修好了。#include<bits/stdc++.h> #define ety -114411441144123 typedef long long ll; using namespace std; struct node{ int l; int r; ll num; }tree[10000001]; ll arr[10000001],n; ll tag1[10000001],tag2[10000001]; void createTree(ll sp,ll l,ll r){ tree[sp].l=l; tree[sp].r=r; if(l==r){ tree[sp].num=arr[l]; return; } ll mid=(l+r)>>1; createTree(sp<<1,l,mid); createTree((sp<<1)+1,mid+1,r); tree[sp].num=max(tree[sp<<1].num,tree[(sp<<1)+1].num); } void cltag2(ll sp){ tree[sp<<1].num+=tag2[sp];tree[(sp<<1)+1].num+=tag2[sp]; tag2[sp<<1]+=tag2[sp]; tag2[(sp<<1)+1]+=tag2[sp]; tag2[sp]=0; } void cltag1(ll sp){ if(tag1[sp]!=ety){ tree[sp<<1].num=tag1[sp];tree[(sp<<1)+1].num=tag1[sp]; tag1[sp<<1]=tag1[(sp<<1)+1]=tag1[sp]; tag1[sp]=ety; } } void areaChange(ll sp,ll l,ll r,ll c){ if(tree[sp].l>=l&&tree[sp].r<=r){ tag1[sp]=c; tree[sp].num=c; return; } cltag1(sp); ll mid=(tree[sp].l+tree[sp].r)>>1; if(l<=mid)areaChange(sp<<1,l,r,c); if(r>mid)areaChange((sp<<1)+1,l,r,c); tree[sp].num=max(tree[sp<<1].num,tree[(sp<<1)+1].num); } void areaAdd(ll sp,ll l,ll r,ll c){ if(tree[sp].l>=l&&tree[sp].r<=r){ tag2[sp]+=c; tree[sp].num+=c; return; } cltag2(sp); ll mid=(tree[sp].l+tree[sp].r)>>1; if(l<=mid)areaAdd(sp<<1,l,r,c); if(r>mid)areaAdd((sp<<1)+1,l,r,c); tree[sp].num=max(tree[sp<<1].num,tree[(sp<<1)+1].num); } ll areaAsk(ll sp,ll l,ll r){ if(tree[sp].l>=l&&tree[sp].r<=r)return tree[sp].num; cltag1(sp); cltag2(sp); ll maxn=0; ll mid=(tree[sp].l+tree[sp].r)>>1; if(l<=mid)maxn=max(maxn,areaAsk(sp<<1,l,r)); if(r>mid)maxn=max(maxn,areaAsk((sp<<1)+1,l,r)); return maxn; } int main(){ // freopen("in.in","r",stdin); // freopen("out.out","w",stdout); cin.tie(0);cout.tie(0); ios::sync_with_stdio(false); fill(tag1,tag1+10000000,ety); ll q; cin>>n>>q; for(ll i=1;i<=n;i++)cin>>arr[i]; createTree(1,1,n); while(q--){ int m; cin>>m; if(m==1){ ll l,r,x; cin>>l>>r>>x; areaChange(1,l,r,x); }else if(m==2){ ll l,r,x; cin>>l>>r>>x; areaAdd(1,l,r,x); }else{ ll l,r; cin>>l>>r; cout<<areaAsk(1,l,r)<<endl; } } }
错误示范3正确呆码修改了前面的所有错误。
#include<bits/stdc++.h> #define ety -114411441144123 typedef long long ll; using namespace std; struct node{ int l; int r; ll num; }tree[10000001]; ll arr[10000001],n; ll tag1[10000001],tag2[10000001]; void createTree(ll sp,ll l,ll r){ tree[sp].l=l; tree[sp].r=r; tree[sp].num=-100000000000000; if(l==r){ tree[sp].num=arr[l]; return; } ll mid=(l+r)>>1; createTree(sp<<1,l,mid); createTree((sp<<1)+1,mid+1,r); tree[sp].num=max(tree[sp<<1].num,tree[(sp<<1)+1].num); } void cltag(ll sp){ if(tag1[sp]!=ety){ tag1[sp<<1]=tag1[(sp<<1)+1]=tag1[sp]; tag2[sp<<1]=tag2[(sp<<1)+1]=tag2[sp];//如果不是先改变数再加上数,加就没有意义了 tree[sp<<1].num=tree[(sp<<1)+1].num=tag1[sp]+tag2[sp]; tag1[sp]=ety; }else{ tag2[sp<<1]+=tag2[sp];tag2[(sp<<1)+1]+=tag2[sp]; tree[sp<<1].num+=tag2[sp];tree[(sp<<1)+1].num+=tag2[sp]; } tag2[sp]=0; } void areaChange(ll sp,ll l,ll r,ll c){ if(tree[sp].l>=l&&tree[sp].r<=r){ tag1[sp]=c; tree[sp].num=c; tag2[sp]=0;//改变后加的数全部没用了 return; } cltag(sp); ll mid=(tree[sp].l+tree[sp].r)>>1; if(l<=mid)areaChange(sp<<1,l,r,c); if(r>mid)areaChange((sp<<1)+1,l,r,c); tree[sp].num=max(tree[sp<<1].num,tree[(sp<<1)+1].num); } void areaAdd(ll sp,ll l,ll r,ll c){ if(tree[sp].l>=l&&tree[sp].r<=r){ tag2[sp]+=c; tree[sp].num+=c; return; } cltag(sp); ll mid=(tree[sp].l+tree[sp].r)>>1; if(l<=mid)areaAdd(sp<<1,l,r,c); if(r>mid)areaAdd((sp<<1)+1,l,r,c); tree[sp].num=max(tree[sp<<1].num,tree[(sp<<1)+1].num); } ll areaAsk(ll sp,ll l,ll r){ if(tree[sp].l>=l&&tree[sp].r<=r)return tree[sp].num; cltag(sp); ll maxn=-100000000000000; ll mid=(tree[sp].l+tree[sp].r)>>1; if(l<=mid)maxn=max(maxn,areaAsk(sp<<1,l,r)); if(r>=mid+1)maxn=max(maxn,areaAsk((sp<<1)+1,l,r)); return maxn; } int main(){ // freopen("in.in","r",stdin); // freopen("out.out","w",stdout); cin.tie(0);cout.tie(0); ios::sync_with_stdio(false); fill(tag1,tag1+10000000,ety); ll q; cin>>n>>q; for(ll i=1;i<=n;i++)cin>>arr[i]; createTree(1,1,n); while(q--){ int m; cin>>m; if(m==1){ ll l,r,x; cin>>l>>r>>x; areaChange(1,l,r,x); }else if(m==2){ ll l,r,x; cin>>l>>r>>x; areaAdd(1,l,r,x); }else{ ll l,r; cin>>l>>r; cout<<areaAsk(1,l,r)<<endl; } } }
- 1
Information
- ID
- 294
- Time
- 2000ms
- Memory
- 512MiB
- Difficulty
- 9
- Tags
- # Submissions
- 103
- Accepted
- 6
- Uploaded By