吉司机线段树求调
查看原帖
吉司机线段树求调
961972
Lele_Programmer楼主2024/7/15 22:45

看了很多题解,好像都有对于最大值和历史最大值的懒标记,有些是将最大值与非最大值区分开,那为什么我这样写不行呢?这样写的思路有什么错误吗?

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int N=500005;
const int inf=1e18;

int n,m;
int arr[N];

struct SegmentTree {
    int l,r;
    int sum;
    int max;
    int cnt;
    int his_max;
    int submax;
    int add;
    int tag;
} tr[N*4];

void pushup(int u) {
    auto &root=tr[u],&left=tr[u<<1],&right=tr[u<<1|1];
    root.sum=left.sum+right.sum;
    root.max=max(left.max,right.max);
    root.his_max=max(left.his_max,right.his_max);
    if (left.max==right.max) {
        root.submax=max(left.submax,right.submax);
        root.cnt=left.cnt+right.cnt;
    } else if (left.max>right.max) {
        root.submax=max(left.submax,right.max);
        root.cnt=left.cnt;
    } else {
        root.submax=max(left.max,right.submax);
        root.cnt=right.cnt;
    }
}

void pushtag(int u,int tag) {
    if (tr[u].max<=tag) return;
    tr[u].sum-=tr[u].cnt*(tr[u].max-tag);
    tr[u].max=tag;
    tr[u].tag=tag;
}

void pushadd(int u) {
    auto &root=tr[u],&left=tr[u<<1],&right=tr[u<<1|1];
    if (root.add) {
        left.add+=root.add;
        right.add+=root.add;
        left.sum+=(left.r-left.l+1)*root.add;
        right.sum+=(right.r-right.l+1)*root.add;
        left.max+=root.add;
        right.max+=root.add;
        if (left.submax!=-inf) left.submax+=root.add;
        if (right.submax!=-inf) right.submax+=root.add;
        left.his_max=max(left.his_max,left.max);
        right.his_max=max(right.his_max,right.max);
        root.add=0;
    }
}

void pushmin(int u) {
    if (tr[u].tag==inf) return;
    pushtag(u<<1,tr[u].tag);
    pushtag(u<<1|1,tr[u].tag);
    tr[u].tag=inf;
}

void pushdown(int u) {
    pushmin(u);
    pushadd(u);
}

void build(int u,int l,int r) {
    tr[u]={l,r,arr[l],arr[l],1,arr[l],-inf,0,inf};
    if (l==r) return;
    int mid=l+r>>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
    pushup(u);
}

void modify_add(int u,int l,int r,int k) {
    if (tr[u].l>=l && tr[u].r<=r) {
        if (tr[u].l!=tr[u].r) pushdown(u);
        tr[u].add+=k;
        tr[u].sum+=(tr[u].r-tr[u].l+1)*k;
        tr[u].max+=k;
        tr[u].his_max=max(tr[u].his_max,tr[u].max);
        if (tr[u].submax!=-inf) tr[u].submax+=k;
    } else {
        pushdown(u);
        int mid=tr[u].l+tr[u].r>>1;
        if (l<=mid) modify_add(u<<1,l,r,k);
        if (r>mid) modify_add(u<<1|1,l,r,k);
        pushup(u);
    }
}

void modify_min(int u,int l,int r,int k) {
    if (tr[u].max<=k) return;
    if (tr[u].l>=l && tr[u].r<=r && k>tr[u].submax) {
        if (tr[u].l!=tr[u].r) pushdown(u);
        pushtag(u,k);
    } else {
        pushdown(u);
        int mid=tr[u].l+tr[u].r>>1;
        if (l<=mid) modify_min(u<<1,l,r,k);
        if (r>mid) modify_min(u<<1|1,l,r,k);
        pushup(u);
    }
}

int query_max(int u,int l,int r) {
    if (tr[u].l>=l && tr[u].r<=r) return tr[u].max;
    pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    int ans=-inf;
    if (l<=mid) ans=max(ans,query_max(u<<1,l,r));
    if (r>mid) ans=max(ans,query_max(u<<1|1,l,r));
    return ans;
}

int query_sum(int u,int l,int r) {
    if (tr[u].l>=l && tr[u].r<=r) return tr[u].sum;
    pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    int ans=0;
    if (l<=mid) ans+=query_sum(u<<1,l,r);
    if (r>mid) ans+=query_sum(u<<1|1,l,r);
    return ans;
}

int query_his_max(int u,int l,int r) {
    if (tr[u].l>=l && tr[u].r<=r) return tr[u].his_max;
    pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    int ans=-inf;
    if (l<=mid) ans=max(ans,query_his_max(u<<1,l,r));
    if (r>mid) ans=max(ans,query_his_max(u<<1|1,l,r));
    return ans;
}

signed main() {
    // freopen("P6242_2.in","r",stdin);
    // freopen("P6242_2","w",stdout);
    scanf("%lld %lld",&n,&m);
    for (int i=1;i<=n;++i) {
        scanf("%lld",&arr[i]);
    }
    build(1,1,n);
    while (m--) {
        int op,l,r;
        scanf("%lld %lld %lld",&op,&l,&r);
        if (op==1) {
            int k;
            scanf("%lld",&k);
            modify_add(1,l,r,k);
        } else if (op==2) {
            int v;
            scanf("%lld",&v);
            modify_min(1,l,r,v);
        } else if (op==3) {
            printf("%lld\n",query_sum(1,l,r));
        } else if (op==4) {
            printf("%lld\n",query_max(1,l,r));
        } else {
            printf("%lld\n",query_his_max(1,l,r));
        }
    }
    return 0;
}
2024/7/15 22:45
加载中...