AlanFong @ 2024-08-23 16:23:32
rt
下载数据在本地跑没有问题,到了洛谷上就MLE/TLE
#include<bits/stdc++.h>
using namespace std;
struct node{
int l,r,laz1,laz2,max;
};
node tree[4000005];
int a[1000005];
int upd(int p)
{
tree[p].l=tree[2*p].l;
tree[p].r=tree[2*p+1].r;
tree[p].max=max(tree[2*p].max,tree[2*p+1].max);
}
void build(int p,int l,int r)
{
if(l==r)
{
tree[p].l=l;
tree[p].r=r;
tree[p].max=a[l];
return ;
}
int mid=(l+r)/2;
build(2*p,l,mid);
build(2*p+1,mid+1,r);
upd(p);
}
void pushd(int p)
{
if(tree[p].laz1!=0)
{
tree[2*p].laz1=tree[p].laz1;
tree[2*p+1].laz1=tree[p].laz1;
tree[2*p].max=tree[p].laz1;
tree[2*p+1].max=tree[p].laz1;
}
else{
if(tree[2*p].laz1!=0)
{
tree[2*p].laz1+=tree[p].laz2;
tree[2*p].max+=tree[p].laz2;
}else{
tree[2*p].laz2+=tree[p].laz2;
tree[2*p].max+=tree[p].laz2;
}
if(tree[2*p+1].laz1!=0)
{
tree[2*p+1].laz1+=tree[p].laz2;
tree[2*p+1].max+=tree[p].laz2;
}else{
tree[2*p+1].laz2+=tree[p].laz2;
tree[2*p+1].max+=tree[p].laz2;
}
}
tree[p].laz2=0;
tree[p].laz1=0;
}
void cover(int p,int l,int r,int x)
{
if(l>r)
{
return;
}
if(tree[p].l==l&&tree[p].r==r)
{
tree[p].laz1=x;
tree[p].laz2=0;
tree[p].max=x;
return;
}
if(tree[p].laz1!=0||tree[p].laz2!=0)
{
pushd(p);
}
if(r<=tree[2*p].r)
{
cover(2*p,l,r,x);
}else if(l>=tree[2*p+1].l)
{
cover(2*p+1,l,r,x);
}else{
cover(2*p,l,tree[2*p].r,x);
cover(2*p+1,tree[2*p+1].l,r,x);
}
upd(p);
}
void change2(int p,int l,int r,int x)
{
if(l>r)
{
return;
}
if(tree[p].l==l&&tree[p].r==r)
{
if(tree[p].laz1!=0)
{
tree[p].laz1+=x;
}else{
tree[p].laz2+=x;
}
tree[p].max+=x;
return;
}
if(tree[p].laz1!=0||tree[p].laz2!=0)
{
pushd(p);
}
if(r<=tree[2*p].r)
{
change2(2*p,l,r,x);
}else if(l>=tree[2*p+1].l)
{
change2(2*p+1,l,r,x);
}else{
change2(2*p,l,tree[2*p].r,x);
change2(2*p+1,tree[2*p+1].l,r,x);
}
upd(p);
}
int search(int p,int l,int r)
{
if(l==tree[p].l&&r==tree[p].r)
{
return tree[p].max;
}
if(tree[p].laz1!=0||tree[p].laz2!=0)
{
pushd(p);
}
if(r<=tree[2*p].r)
{
return search(2*p,l,r);
}else if(l>=tree[2*p+1].l)
{
return search(2*p+1,l,r);
}else{
return max(search(2*p,l,tree[2*p].r),search(2*p+1,tree[2*p+1].l,r));
}
}
signed main()
{
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build(1,1,n);
while(q--)
{
int op;
cin>>op;
if(op==1)
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
cover(1,l,r,x);
}else if(op==2)
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
change2(1,l,r,x);
}else{
int l,r;
scanf("%d%d",&l,&r);
cout<<search(1,l,r)<<endl;
}
}
return 0;
}
by zhaomumu1218 @ 2024-08-23 20:42:44
@AlanFong A了
by Hog_Dawa_IOI @ 2024-08-23 20:44:54
#include<bits/stdc++.h>
using namespace std;
struct node{
int l,r;long long laz1,laz2,max;
};
node tree[4000005];
long long a[1000005];
void upd(int p)//没返回值不要加int
{
if(tree[p].l!=tree[p].r) tree[p].max=max(tree[2*p].max,tree[2*p+1].max);
//如果本身不是叶子节点才读取儿子的信息,有的时候问题不大有的时候问题很大,建议以后都写上
}
void build(int p,int l,int r)
{
tree[p].l=l;
tree[p].r=r;//建议在build就记录好l和r的信息
if(l==r)
{
tree[p].max=a[l]+1000000000000005;//见主函数,后面细讲
return ;
}
int mid=(l+r)/2;
build(2*p,l,mid);
build(2*p+1,mid+1,r);
upd(p);
}
void pushd(int p)
{if(tree[p].l!=tree[p].r)
{if(tree[p].laz1) tree[2*p].max=tree[2*p+1].max=tree[2*p].laz1=tree[2*p+1].laz1=tree[p].laz1,
tree[2*p].laz2=tree[2*p+1].laz2=tree[p].laz1=0;
if(tree[p].laz2) tree[2*p].max+=tree[p].laz2,tree[2*p].laz2+=tree[p].laz2,tree[2*p+1].max+=tree[p].laz2,
tree[2*p+1].laz2+=tree[p].laz2,tree[p].laz2=0;//你的pushdown抽象炸了,感觉你对优先级的理解都有点问题
}//在这里是cover的优先级大于add的优先级,但是在cover之后也是需要add的,要不然down不干净
//注意这里的laz我给它设了0的初值,后面细讲,如果不用到后面的改法,这里是不能设0的
/*if(tree[p].laz1!=0)
{
tree[2*p].laz1=tree[p].laz1;
tree[2*p+1].laz1=tree[p].laz1;
tree[2*p].max=tree[p].laz1;
tree[2*p+1].max=tree[p].laz1;
}
else{
if(tree[2*p].laz1!=0)
{
tree[2*p].laz1+=tree[p].laz2;
tree[2*p].max+=tree[p].laz2;
}else{
tree[2*p].laz2+=tree[p].laz2;
tree[2*p].max+=tree[p].laz2;
}
if(tree[2*p+1].laz1!=0)
{
tree[2*p+1].laz1+=tree[p].laz2;
tree[2*p+1].max+=tree[p].laz2;
}else{
tree[2*p+1].laz2+=tree[p].laz2;
tree[2*p+1].max+=tree[p].laz2;
}
}
tree[p].laz2=0;
tree[p].laz1=0;*/
}
void cover(int p,int l,int r,long long x)
{
// printf("%d %d %d %d\n",tree[p].l,tree[p].r,l,r);
/*if(l>r)//这句话有没有都一样
{
return;
}*/if(r<tree[p].l||tree[p].r<l) return;
pushd(p);
if(tree[p].l>=l&&tree[p].r<=r)//不是哥们儿你这是纯粗心了吧
{
tree[p].laz1=x;
tree[p].laz2=0;
tree[p].max=x;
return;
}
if(tree[p].laz1!=0||tree[p].laz2!=0)
{
pushd(p);
}
cover(p<<1,l,r,x),cover(p<<1|1,l,r,x);
/*if(r<=tree[2*p].r)
{
cover(2*p,l,r,x);
}if(l>=tree[2*p+1].l)//建议学习主流线段树写法,你这样有大错,万一2个都满足呢
//我还是给你改成主流写法算了
{
cover(2*p+1,l,r,x);
}*/
upd(p);
}
void change2(int p,int l,int r,long long x)
{
/*if(l>r)//同上
{
return;
}*/
if(r<tree[p].l||tree[p].r<l) return;
pushd(p);
if(tree[p].l>=l&&tree[p].r<=r)//同上
{
/*if(tree[p].laz1!=0)
{
tree[p].laz1+=x;
}else{
tree[p].laz2+=x;
}*/
tree[p].laz2+=x;//这里也错了
//结合上下文,laz1维护的是覆盖的标记,laz2维护的是加的标记,二者不要混用
//直接laz2+=x就可以了
tree[p].max+=x;
return;
}
/*if(tree[p].laz1!=0||tree[p].laz2!=0)
{
pushd(p);
}*/change2(p<<1,l,r,x),change2(p<<1|1,l,r,x);
/*if(r<=tree[2*p].r)
{
change2(2*p,l,r,x);
}if(l>=tree[2*p+1].l)
{
change2(2*p+1,l,r,x);
}*///同上
upd(p);
}
long long search(int p,int l,int r)
{
pushd(p);
if(r<tree[p].l||tree[p].r<l) return -1;
if(l<=tree[p].l&&r>=tree[p].r)//同上
{
return tree[p].max;
}
/*if(tree[p].laz1!=0||tree[p].laz2!=0)
{
pushd(p);
}*/return max(search(p<<1,l,r),search(p<<1|1,l,r));
/*if(r<=tree[2*p].r)
{
ans=max(ans, search(2*p,l,r));
}if(l>=tree[2*p+1].l)
{
ans=max(ans,search(2*p+1,l,r));
}return ans;*///同上
}
signed main()
{
int n,q;scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
build(1,1,n);
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
long long l,r,x;
scanf("%lld%lld%lld",&l,&r,&x);
cover(1,l,r,x+1000000000000005);
//这里sunnycl也说过了,因为有负数,所以不能直接用0代表懒标记的初值
//但是特判太麻烦怎么办?
//可以对值域整体往上移,只需要对数字整体加上一个初值就可以了
//但是不能单纯加上1e9,因为如果10^6次加法全是+1e9,那么最大值会变为1e15,所以我们需要整体平移1e15
//此时需要开long long
}else if(op==2)
{
long long l,r,x;
scanf("%lld%lld%lld",&l,&r,&x);
change2(1,l,r,x);
}else{
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",search(1,l,r)-1000000000000005);
}
}
return 0;
}
A 了(把pushd放到特判后面qwq)