所谓吉司机线段树,就是吉司机种的线段树
(逃)
解析
之前也看过一些相关内容的博客,但是因标记乱七八糟,感觉过于高深而放弃了…
直到看到洛谷这篇博客,完全颠覆了我的认知。(怎么感觉语气像营销号)
原来是很小清新的算法,记录的标记虽然不少,但关键其实就在于记录懒标记历史最值这个操作上,而且思路很自然。
再次强推这篇博客!
在它的光辉下,一切更多的文字都是多余的。
我可不是在水文啊
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned ll
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read() {ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}const int N=5e5+100;
const int inf=1e9;int n,m;#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs (k<<1|1)
struct tree{int siz,maxa,maxb,add1,add2,add3,add4,sec,cnt;ll sum;
}tr[N<<2];
inline void pushup(int k){tr[k].siz=tr[ls].siz+tr[rs].siz;tr[k].sum=tr[ls].sum+tr[rs].sum;tr[k].maxa=max(tr[ls].maxa,tr[rs].maxa);tr[k].maxb=max(tr[ls].maxb,tr[rs].maxb);tr[k].sec=max(tr[ls].sec,tr[rs].sec);if(tr[ls].maxa<tr[k].maxa) tr[k].sec=max(tr[k].sec,tr[ls].maxa);if(tr[rs].maxa<tr[k].maxa) tr[k].sec=max(tr[k].sec,tr[rs].maxa);tr[k].cnt=0;if(tr[k].maxa==tr[ls].maxa) tr[k].cnt+=tr[ls].cnt;if(tr[k].maxa==tr[rs].maxa) tr[k].cnt+=tr[rs].cnt;return;
}
inline void Add(int k,int add1,int add2,int add3,int add4){tr[k].sum+=1ll*tr[k].cnt*add1+1ll*(tr[k].siz-tr[k].cnt)*add2;tr[k].maxb=max(tr[k].maxb,tr[k].maxa+add3);tr[k].maxa+=add1;tr[k].add3=max(tr[k].add3,tr[k].add1+add3);tr[k].add4=max(tr[k].add4,tr[k].add2+add4);tr[k].add1+=add1;tr[k].add2+=add2;tr[k].sec+=add2;return;
}
inline void pushdown(int k){ll mx=max(tr[ls].maxa,tr[rs].maxa);if(mx==tr[ls].maxa) Add(ls,tr[k].add1,tr[k].add2,tr[k].add3,tr[k].add4);else Add(ls,tr[k].add2,tr[k].add2,tr[k].add4,tr[k].add4);if(mx==tr[rs].maxa) Add(rs,tr[k].add1,tr[k].add2,tr[k].add3,tr[k].add4);else Add(rs,tr[k].add2,tr[k].add2,tr[k].add4,tr[k].add4);tr[k].add1=tr[k].add2=tr[k].add3=tr[k].add4=0;
}
int a[N];
void build(int k,int l,int r){if(l==r){tr[k].siz=1;tr[k].maxa=tr[k].maxb=tr[k].sum=a[l];tr[k].cnt=1;tr[k].sec=-inf;tr[k].add1=tr[k].add2=tr[k].add3=tr[k].add4=0;return;}build(ls,l,mid);build(rs,mid+1,r);pushup(k);return;
}
void upd_add(int k,int l,int r,int x,int y,int w){if(x<=l&&r<=y){Add(k,w,w,w,w);return;}pushdown(k);if(x<=mid) upd_add(ls,l,mid,x,y,w);if(y>mid) upd_add(rs,mid+1,r,x,y,w);pushup(k);
}
void upd_min(int k,int l,int r,int x,int y,int w){if(tr[k].maxa<=w) return;if(x<=l&&r<=y&&tr[k].sec<w){Add(k,w-tr[k].maxa,0,w-tr[k].maxa,0);return;}pushdown(k);if(x<=mid) upd_min(ls,l,mid,x,y,w);if(y>mid) upd_min(rs,mid+1,r,x,y,w);pushup(k);
}
ll ask_sum(int k,int l,int r,int x,int y){if(x<=l&&r<=y) return tr[k].sum;ll res(0);pushdown(k);if(x<=mid) res+=ask_sum(ls,l,mid,x,y);if(y>mid) res+=ask_sum(rs,mid+1,r,x,y);return res;
}
ll ask_maxa(int k,int l,int r,int x,int y){if(x<=l&&r<=y) return tr[k].maxa;ll res=-inf;pushdown(k);if(x<=mid) res=max(res,ask_maxa(ls,l,mid,x,y));if(y>mid) res=max(res,ask_maxa(rs,mid+1,r,x,y));return res;
}
ll ask_maxb(int k,int l,int r,int x,int y){if(x<=l&&r<=y) return tr[k].maxb;ll res=-inf;pushdown(k);if(x<=mid) res=max(res,ask_maxb(ls,l,mid,x,y));if(y>mid) res=max(res,ask_maxb(rs,mid+1,r,x,y));return res;
}signed main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifn=read();m=read();for(int i=1;i<=n;i++) a[i]=read();build(1,1,n);for(int i=1;i<=m;i++){int op=read(),l=read(),r=read(),w;if(op<=2) w=read();if(op==1) upd_add(1,1,n,l,r,w);else if(op==2) upd_min(1,1,n,l,r,w);else if(op==3) printf("%lld\n",ask_sum(1,1,n,l,r));else if(op==4) printf("%lld\n",ask_maxa(1,1,n,l,r));else printf("%lld\n",ask_maxb(1,1,n,l,r));}return 0;
}
/*
*/