线段树求调,玄关

P1253 扶苏的问题

lwxxs @ 2024-04-05 13:23:18

#include<cstring>
#include<iostream>
#include<algorithm>
#include<limits.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
const int inf=1e9+10;
int n,m;
ll w[N];
struct node{
    int l,r;
    ll add;
    int reset;
    ll maxv;
}tr[N*4];
void pushup(int u){
    tr[u].maxv=max(tr[u<<1].maxv,tr[u<<1|1].maxv);
}
void pushdown(int u){
    if(tr[u].add){
       if(tr[u<<1].reset!=inf){
           tr[u<<1].reset+=tr[u].add;
           tr[u<<1].maxv=tr[u<<1].reset;
       }
       else{
           tr[u<<1].add+=tr[u].add;
           tr[u<<1].maxv+=tr[u].add;
       }
       if(tr[u<<1|1].reset!=inf){
           tr[u<<1|1].reset+=tr[u].add;
           tr[u<<1|1].maxv+=tr[u<<1|1].reset;
       }
       else{
           tr[u<<1|1].add+=tr[u].add;
           tr[u<<1|1].maxv+=tr[u].add;
       }
       tr[u].add=0;
    }
    if(tr[u].reset!=inf){
        tr[u<<1].add=0;
        tr[u<<1].reset=tr[u].reset;
        tr[u<<1].maxv=tr[u].reset;
        tr[u<<1|1].add=0;
        tr[u<<1|1].reset=tr[u].reset;
        tr[u<<1|1].maxv=tr[u].reset;
        tr[u].reset=inf;
    }
}
void build(int u,int l,int r){
    tr[u]={l,r,0,inf,0};
    if(l==r){
        tr[u].maxv=w[l];
    }
    else{
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        pushup(u);
    }
}
void modify1(int u,int l,int r,int x){
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].maxv=x;
        tr[u].add=0;
        tr[u].reset=x;
        return;
    }
    else{
        pushdown(u);
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)modify1(u<<1,l,r,x);
        if(r>mid)modify1(u<<1|1,l,r,x);
        pushup(u);
    }
}
void modify2(int u,int l,int r,int x){
    if(tr[u].l>=l&&tr[u].r<=r){
        if(tr[u].reset!=inf){
            tr[u].reset+=x;
            tr[u].maxv+=x;
            return;
        }
        else{
            tr[u].add+=x;
            tr[u].maxv+=x;
            return;
        }
    }
    else{
        pushdown(u);
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)modify2(u<<1,l,r,x);
        if(r>mid)modify2(u<<1|1,l,r,x);
        pushup(u);
    }
}
ll query(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r){
        return tr[u].maxv;
    }
    else{
        pushdown(u);
        ll maxv=-LLONG_MAX;
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)maxv=max(maxv, query(u<<1,l,r));
        if(r>mid)maxv=max(maxv,query(u<<1|1,l,r));
        return maxv;
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>w[i];
    }
    build(1,1,n);
    while(m--){
        int opt;
        cin>>opt;
        if(opt==1){
            int l,r,x;
            cin>>l>>r>>x;
            modify1(1,l,r,x);//gaiweix;
        }
        else if(opt==2){
            int l,r,x;
            cin>>l>>r>>x;
            modify2(1,l,r,x);
        }
        else if(opt==3){
            int l,r;
            cin>>l>>r;
            cout<<query(1,l,r)<<endl;
        }
    }
    return 0;
}

by lwxxs @ 2024-04-05 13:24:45

60pts,最后一个点超时,七八九测试点WA


by wrh316 @ 2024-04-05 14:17:20

@lwxxs 你这线段树是不是写复杂了

模版,我不知道要不要改

void pushup(int k){
    sum[k] = sum[k << 1] + sum[k << 1 | 1];
    return ;
}
void build(int k,int l,int r){
    if(l == r){
        sum[k] = a[l];
        return ;
    }
    int mid = (l + r) >> 1;
    build(k << 1,l,mid);
    build(k << 1 | 1,mid + 1,r);
    pushup(k);
    return ;
}
void change(int k,int l,int r,int v){
    sum[k] += (ll)v * (r - l + 1);
    add[k] += v;
    return ;
}
void pushdown(int k,int l,int r){
    if(add[k]){
        int mid = (l + r) >> 1;
        change(k << 1,l,mid,add[k]);
        change(k << 1 | 1,mid + 1,r,add[k]);
        add[k] = 0;
    }
    return ;
}
void update(int k,int l,int r,int x,int y,int v){
    if(l >= x && r <= y){
        change(k,l,r,v);
        return ;
    }
    pushdown(k,l,r);
    int mid = (l + r) >> 1;
    if(x <= mid) update(k << 1,l,mid,x,y,v);
    if(y >= mid + 1) update(k << 1 | 1,mid + 1,r,x,y,v);
    pushup(k);
    return ;
}
ll query(int k,int l,int r,int x,int y){
    if(l >= x && r <= y) return sum[k];
    pushdown(k,l,r);
    int mid = (l + r) >> 1;
    ll res = 0;
    if(x <= mid) res = query(k << 1,l,mid,x,y);
    if(y >= mid + 1) res += query(k << 1 | 1,mid + 1,r,x,y);
    return res;
}

by Leo_SZ @ 2024-04-05 21:47:16

@lwxxs 两个错误:

  1. pushdown函数里面有一个=打成了+=
    if(tr[u<<1|1].reset!=inf){
    tr[u<<1|1].reset+=tr[u].add;
    tr[u<<1|1].maxv+=tr[u<<1|1].reset;//here
    }
  2. reset 也要用 long long
    ll add;
    int reset;//here
    ll maxv;

by Leo_SZ @ 2024-04-05 22:53:55

对于超时,题目已经提示:请注意大量数据读入对程序效率造成的影响。所以请将 cin 换成 scanf 或快读。


by lwxxs @ 2024-04-06 18:51:20

@Leo_SZ 感谢大佬,已关


by lwxxs @ 2024-04-06 18:51:58

此贴完结


|