陈asuna @ 2024-02-27 00:58:05
一般来说,6-10是因为负值的原因,但是我觉得我的负值开的够小来着。本人刚学几星期的菜鸡,有无大佬帮帮忙来着,感谢
#include<bits/stdc++.h>
using namespace std;
#define lc p*2
#define rc p*2+1
#define ll long long
const ll INF =0x3f3f3f3f3f3f3f3f;
const int N=1e7+20;
struct node
{
ll l,r,maxn,add1,add2,flag;
}tr[4*N];
ll w[N];
void pushup(ll p)
{
//cout<<"lc "<<lc<<" "<<tr[lc].maxn<<" rc "<<rc<<" "<<tr[rc].maxn<<endl;
tr[p].maxn=max(tr[lc].maxn,tr[rc].maxn);
//cout<<"p "<<p<<endl;
}
void build(ll p,ll l,ll r)
{
tr[p]={l,r,w[l],0};
tr[p].flag=0;
if(l==r) return;
ll m=l+r>>1;
build(lc,l,m);
build(rc,m+1,r);
pushup(p);
}
void pushdown2(ll p)
{
if(tr[p].flag)
{
tr[lc].flag=tr[p].flag;
tr[rc].flag=tr[p].flag;
tr[lc].maxn=tr[p].add2;
tr[rc].maxn=tr[p].add2;
tr[p].flag=0;
tr[p].add1=tr[lc].add1=tr[rc].add1=0;
}
}
void pushdown1(ll p)
{
pushdown2(p);
if(tr[p].add1)
{
tr[lc].add1+=tr[p].add1;
tr[rc].add1+=tr[p].add1;
tr[lc].maxn+=tr[p].add1;
tr[rc].maxn+=tr[p].add1;
tr[p].add1=0;
}
}
void update1(ll p,ll x,ll y,ll k)
{
//cout<<"p1 "<<p<<" "<<tr[p].maxn<<" "<<x<<y<<tr[p].l<<tr[p].r<<endl;
if(x<=tr[p].l&&tr[p].r<=y)
{
//cout<<p<<endl;
tr[p].maxn+=k;
tr[p].add1+=k;
return;
}
ll m=tr[p].l+tr[p].r>>1;
pushdown2(p);
pushdown1(p);
if(x<=m) update1(lc,x,y,k);
if(m<y) update1(rc,x,y,k);
pushup(p);
}
void update2(ll p,ll x,ll y,ll k)
{
if(x<=tr[p].l&&tr[p].r<=y)
{
tr[p].maxn=k;
//cout<<p<<" "<<tr[p].maxn<<endl;
tr[p].flag=1;
tr[p].add2=k;
return;
}
ll m=tr[p].l+tr[p].r>>1;
pushdown2(p);
pushdown1(p);
if(x<=m) update2(lc,x,y,k);
if(m<y) update2(rc,x,y,k);
pushup(p);
}
ll query(ll p,ll x,ll y)
{
if(x<=tr[p].l&&tr[p].r<=y)
{
//cout<<p<<" "<<tr[p].maxn<<endl;
return tr[p].maxn;
}
int m=tr[p].l+tr[p].r>>1;
ll maxn=-INF;
pushdown2(p);
pushdown1(p);
if(x<=m) maxn=max(maxn,query(lc,x,y));
if(y>m) maxn=max(maxn,query(rc,x,y));
pushup(p);
return maxn;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%lld",&w[i]);
}
build(1,1,n);
while(m--)
{
int op;
scanf("%d",&op);
if(op==1)
{
ll l,r,x;
scanf("%lld%lld%lld",&l,&r,&x);
update2(1,l,r,x);
}
else if(op==2)
{
ll l,r,x;
scanf("%lld%lld%lld",&l,&r,&x);
update1(1,l,r,x);
}
else if(op==3)
{
ll l,r;
scanf("%lld%lld",&l,&r);
printf("%d\n",query(1,l,r));
}
}
return 0;
}
by UMS2 @ 2024-02-27 07:15:37
pushdown2内不要把p的add1归零。
考虑先覆盖再加,你的pushdown2会把加的标记抹掉。
by UMS2 @ 2024-02-27 07:21:17
update1内覆盖时要将加的标记消除。
并且里面pushdown2可以删掉,你的pushdown1里面已经有了。
by UMS2 @ 2024-02-27 07:23:30
query里没有必要pushup,此外应该没啥问题 @陈asuna
by UMS2 @ 2024-02-27 07:29:32
优化的话可以把覆盖和加单独做成两个函数,这样 pushdown 和 update 的时候直接调用。
可以把 pushdown2 并到 pushdown1 里用两个 if 并列。
flag 和 add2可以写成一个,把 add2 默认值设置成 inf 就可以实现。
by UMS2 @ 2024-02-27 07:35:57
build 里面,应该是要到 l==r 时再赋值,不应该直接赋值。
void build(int k,int l,int r){
line[k].l=l,line[k].r=r;
line[k].upt=inf;
if(l==r){
line[k].val=w[l];
return;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
kp(k);
}
by 陈asuna @ 2024-02-27 11:45:24
@UMS2 感谢大佬,已经AC!其实最后那个op==3写错了,应该是printf("%lld\n"...),改了前头忘改后头了