1. 程式人生 > >UOJ164 V 線段樹lazytag維護歷史最值

UOJ164 V 線段樹lazytag維護歷史最值

題意:維護一列數,支援:
1.區間加A
2.區間減A,減法結束後每個位置與0取max
3.區間覆蓋成A
4.詢問單點當前值
5.詢問單點歷史最值

線段樹lazytag維護歷史最值,要記錄四個陣列,注意轉移以及初始條件。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn=10000010;
const LL INF=1e18;
int n,m;
struct
Tree{ LL add,addmax,r,rmax; }tree[maxn<<2],tmp; int qx; int ql,qr; int type; LL s[maxn]; void build(int o,int l,int r){ if(l==r){ tree[o]=(Tree){0,0,-INF,-INF}; return; } int lc=o<<1,rc=o<<1|1,mid=(l+r)>>1; build(lc,l,mid); build(rc,mid+1
,r); } Tree update(Tree u,Tree v){ return (Tree){ max(u.add+v.add,-INF),max(u.addmax,u.add+v.addmax),max(u.r+v.add,v.r),max(max(u.rmax,v.rmax),u.r+v.addmax) }; } void pushdown(int o){ tree[o<<1]=update(tree[o<<1],tree[o]); tree[o<<1|1]=update(tree[o<<1
|1],tree[o]); tree[o]=(Tree){0,-INF,0,-INF}; } void change(int o,int l,int r){ if(ql<=l && qr>=r){ tree[o]=update(tree[o],tmp); return; } pushdown(o); int lc=o<<1,rc=o<<1|1,mid=(l+r)>>1; if(ql<=mid) change(lc,l,mid); if(qr>mid) change(rc,mid+1,r); } void query(int o,int l,int r){ if(l==r){ if(type==4) printf("%lld\n",max(tree[o].add+s[qx],tree[o].r)); if(type==5) printf("%lld\n",max(tree[o].addmax+s[qx],tree[o].rmax)); return; } pushdown(o); int lc=o<<1,rc=o<<1|1,mid=(l+r)>>1; if(qx<=mid) query(lc,l,mid); else query(rc,mid+1,r); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&s[i]); build(1,1,n); while(m--){ scanf("%d",&type); int x; if(type<=3){ scanf("%d%d",&ql,&qr); scanf("%d",&x); if(type==1)tmp=(Tree){x,x,-INF,-INF}; if(type==2)tmp=(Tree){-x,-x,0,0}; if(type==3)tmp=(Tree){-INF,-INF,x,x}; change(1,1,n); }else{ scanf("%d",&qx); query(1,1,n); } } return 0; }

^_^