求调,或者给个hack数据

P1253 扶苏的问题

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].tag1rt[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 updata1updata2query 都存在一个问题。你写的是这样的:

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);
}

|