1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| #include"bits/stdc++.h" #define re register #define int long long #define ls(p) tr[p].ls #define rs(p) tr[p].rs #define pii pair<int,int> #define fi first #define se second using namespace std; const int maxn=2e5+10,inf=1e18; int n,A,B,C,D; int a[maxn],f[maxn]; int L[maxn],R[maxn]; struct Stack{ int top; int stk[maxn]; }mn,mx; namespace tree1{ int rt,segcnt; struct tree{ int ls,rs,mx,tag; }tr[maxn<<1]; inline void up(int p){tr[p].mx=max(tr[ls(p)].mx,tr[rs(p)].mx);} inline void add(int p,int val){tr[p].mx+=val,tr[p].tag+=val;} inline void down(int p){if(tr[p].tag) add(ls(p),tr[p].tag),add(rs(p),tr[p].tag),tr[p].tag=0;} inline void build(int l,int r,int &p){ p=++segcnt;tr[p].mx=tr[p].tag=0; if(l==r) return; int mid=(l+r)>>1; build(l,mid,ls(p)),build(mid+1,r,rs(p)); } inline void update(int l,int r,int L,int R,int val,int p){ if(l>=L&&r<=R){add(p,val);return;} int mid=(l+r)>>1;down(p); if(L<=mid) update(l,mid,L,R,val,ls(p)); if(R>mid) update(mid+1,r,L,R,val,rs(p)); up(p); } inline int query(int l,int r,int L,int R,int p){ if(l>=L&&r<=R) return tr[p].mx; int mid=(l+r)>>1,res=-inf;down(p); if(L<=mid) res=max(res,query(l,mid,L,R,ls(p))); if(R>mid) res=max(res,query(mid+1,r,L,R,rs(p))); return res; } inline void clear(){rt=segcnt=0;} } namespace tree2{ int rt,segcnt; struct tree{ int ls,rs; pii s; }tr[maxn<<1]; inline void up(int p){tr[p].s=min(tr[ls(p)].s,tr[rs(p)].s);} inline void build(int l,int r,int &p){ p=++segcnt; if(l==r){tr[p].s={0,l};return;} int mid=(l+r)>>1; build(l,mid,ls(p)),build(mid+1,r,rs(p)); up(p); } inline void update(int l,int r,int pos,int val,int p){ if(l==r){tr[p].s={val,pos};return;} int mid=(l+r)>>1; if(pos<=mid) update(l,mid,pos,val,ls(p)); else update(mid+1,r,pos,val,rs(p)); up(p); } inline pii query(int l,int r,int pos,int p){ if(tr[p].s.fi>=pos) return {-1,-1}; if(l==r) return tr[p].s; int mid=(l+r)>>1; if(tr[ls(p)].s.fi>=pos) return query(mid+1,r,pos,rs(p)); else return query(l,mid,pos,ls(p)); } inline void clear(){rt=segcnt=0;} } inline void clear(){ for(re int i=0;i<=n;++i) L[i]=R[i]=-1;L[0]=1,R[0]=n; for(re int i=1;i<=n;++i) f[i]=0; mn.top=mx.top=0; tree1::clear();tree2::clear(); } inline void solve(){ cin>>n>>A>>B>>C>>D;clear();tree1::build(0,n,tree1::rt);tree2::build(0,n,tree2::rt); for(re int i=1;i<=n;++i) cin>>a[i]; for(re int i=1,x;i<=n;++i){ while(mx.top&&a[mx.stk[mx.top]]<=a[i]) tree1::update(0,n,mx.stk[mx.top-1],mx.stk[mx.top]-1,-A*a[mx.stk[mx.top]],tree1::rt),--mx.top; tree1::update(0,n,mx.stk[mx.top],i-1,A*a[i],tree1::rt),mx.stk[++mx.top]=i; while(mn.top&&a[mn.stk[mn.top]]>=a[i]) tree1::update(0,n,mn.stk[mn.top-1],mn.stk[mn.top]-1,-B*a[mn.stk[mn.top]],tree1::rt),--mn.top; tree1::update(0,n,mn.stk[mn.top],i-1,B*a[i],tree1::rt),mn.stk[++mn.top]=i; x=a[i]; tree2::update(0,n,x,i,tree2::rt); if(L[x]!=-1){ int l=L[x],r=min(R[x],i); if(x!=0) L[x]=R[x]=-1; else L[x]=i+1; tree1::update(0,n,l-1,r-1,-C*x,tree1::rt); while(l<=r){ pii res=tree2::query(0,n,r,tree2::rt); int pos=res.fi,val=res.se;++pos; if(l<=pos){ L[val]=pos,R[val]=r; tree1::update(0,n,pos-1,r-1,C*val,tree1::rt); } else{ R[val]=r; tree1::update(0,n,l-1,r-1,C*val,tree1::rt); } r=pos-1; } } f[i]=tree1::query(0,n,0,i-1,tree1::rt)+D; tree1::update(0,n,i,i,f[i],tree1::rt); } cout<<f[n]<<'\n'; } signed main(){ freopen("mix.in","r",stdin); freopen("mix.out","w",stdout); ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int T;cin>>T;while(T--) solve(); return 0; }
|