P4314 CPU监控
【题意】
维护一个数据结构支持如下操作:
1.查询当前的区间最大值
2.查询历史上区间最大值
3.区间加 4.区间覆盖
【分析】
这道题目是历史版本维护的一个经典题目
我们记录一个点的tag(x,y)表示先加上x,再与y取max,得到的这个点表示的区间的值
我们为了维护历史的最大值,所以要维护一个maxval和maxtag
两个tag取max,即x和y同时取max
两个tag求和,x就是两个相加,y得讨论,可能第一个覆盖+第二个,也可能是直接覆盖第二个大,取个max即可
然后我们只需要利用这些信息取维护即可
【代码】
#include<bits/stdc++.h> using namespace std; #define mp make_pair #define fi first #define se second #define lson now<<1 #define rson now<<1|1 typedef long long ll; const int maxn=1e5+5; const ll inf=1e17; int n,m; struct seg { ll nowval,lastval; }tr[maxn<<2]; struct tag { ll x,y; void clear() { x=0; y=-inf; } ll calc(ll v) { return max(v+x,y); } }t[maxn<<2],maxt[maxn<<2]; ll v[maxn]; tag max(tag x,tag y) { return (tag){max(x.x,y.x),max(x.y,y.y)}; } tag operator + (tag x,tag y) { return (tag){max(-inf,x.x+y.x),max(x.y+y.x,y.y)}; } void pushup(int now) { tr[now].nowval=max(tr[lson].nowval,tr[rson].nowval); tr[now].lastval=max(tr[lson].lastval,tr[rson].lastval); } void pushtag(int now,tag x,tag y) { maxt[now]=max(maxt[now],t[now]+y); t[now]=t[now]+x; tr[now].lastval=max(tr[now].lastval,y.calc(tr[now].nowval)); tr[now].nowval=x.calc(tr[now].nowval); } void pushdown(int now) { pushtag(lson,t[now],maxt[now]); pushtag(rson,t[now],maxt[now]); t[now].clear(); maxt[now].clear(); } void build(int now,int l,int r) { t[now].clear(); maxt[now].clear(); if(l==r) { tr[now].lastval=tr[now].nowval=v[l]; return; } int mid=(l+r)>>1; build(lson,l,mid); build(rson,mid+1,r); pushup(now); } void update(int now,int l,int r,int L,int R,tag val) { if(l>=L && r<=R) { pushtag(now,val,val); return; } int mid=(l+r)>>1; pushdown(now); if(L<=mid) update(lson,l,mid,L,R,val); if(mid<R) update(rson,mid+1,r,L,R,val); pushup(now); } ll query(int now,int l,int r,int L,int R,int op) { if(l>=L && r<=R) return op==1?tr[now].nowval:tr[now].lastval; int mid=(l+r)>>1; pushdown(now); if(R<=mid) return query(lson,l,mid,L,R,op); if(L>mid) return query(rson,mid+1,r,L,R,op); return max(query(lson,l,mid,L,R,op),query(rson,mid+1,r,L,R,op)); } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&v[i]); scanf("%d",&m); char c[5]; build(1,1,n); int x,y; for(int i=1;i<=m;i++) { scanf("%s",c); scanf("%d%d",&x,&y); tag tmp; tmp.x=tmp.y=-inf; if(c[0]=='Q') printf("%lld\n",query(1,1,n,x,y,1)); if(c[0]=='A') printf("%lld\n",query(1,1,n,x,y,0)); if(c[0]=='P') scanf("%lld",&tmp.x),update(1,1,n,x,y,tmp); if(c[0]=='C') scanf("%lld",&tmp.y),update(1,1,n,x,y,tmp); } return 0; }