题解
算是历史遗留问题的解决
之前队长快跑看题解很迷糊,觉得似懂非懂的,AC但是很水,最后代码都不是我的,是$王_{drink_{grass}}$的
现在总算会了
首先题目中条件就是$max(a)<=b_i$
暴力dp就是$f[i][j]$表示考虑了前$i$个位置最大值为$j$时权值最大是多少
于是分情况讨论
1.$a_i>b_i$
因为要满足$max(a)<=b_i$所以$f[i][a[i]]=max(f[i-1][1],f[i-1][2],,,,,f[i-1][b[i]])+val$这些位置最大值都会改变为$a[i]$
2.$a_i<b_i$
因为要满足$max(a)<=b_i$显然在$a_i--b_i$之间$f[i-1][a[i]]--f[i-1][b[i]]$之间最大值不会变直接+val即可
在$1--a_{i-1}$,最大值变为$a[i]$,于是就有了$f[i][a[i]]=max(f[i-1][1],f[i-1][2],,,,,f[i-1][a[i-1]])+val$
可以用线段树维护
$f[i][a[i]]=max(f[i-1][1],f[i-1][2],,,,,f[i-1][b[i]])+val$
$f[i][a[i]]=max(f[i-1][1],f[i-1][2],,,,,f[i-1][a[i-1]])+val$
就是区间最大值,单点赋值
$f[i-1][a[i]]+val--f[i-1][b[i]]+val$
就是区间+
代码
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 12000000 ll lsh[A]; ll n,maxn,len=0,cnt=0,q; struct node{ ll a,b,w; friend bool operator < (const node &c,const node &d){ return ((c.a+c.b)==(d.a+d.b))?(c.b<d.b):((c.a+c.b)<(d.a+d.b)); } }s[A]; struct tree{ ll l,r,f,val; }tr[A]; void up(ll x){ tr[x].val=max(tr[x<<1].val,tr[x<<1|1].val); } void down(ll x){ tr[x<<1].f+=tr[x].f; tr[x<<1|1].f+=tr[x].f; tr[x<<1].val+=tr[x].f; tr[x<<1|1].val+=tr[x].f; tr[x].f=0; } void built(ll x,ll l,ll r){ tr[x].l=l,tr[x].r=r; if(tr[x].l==tr[x].r){ tr[x].val=0; return ; } ll mid=(l+r)>>1; built(x<<1,l,mid); built(x<<1|1,mid+1,r); up(x); } void seg_max(ll x,ll l,ll r){ if(l>r) return; if(tr[x].f) down(x); if(tr[x].l>=l&&tr[x].r<=r){ maxn=max(maxn,tr[x].val); // maxn=tr[x].val; return ; } ll mid=(tr[x].l+tr[x].r)>>1; if(mid>=l) seg_max(x<<1,l,r); if(mid<r) seg_max(x<<1|1,l,r); } void change(ll x,ll ooo,ll val){ if(tr[x].l==tr[x].r) { tr[x].val=max(tr[x].val,val); return ; } if(tr[x].f) down(x); ll mid=(tr[x].l+tr[x].r)>>1; if(ooo<=mid) change(x<<1,ooo,val); else change(x<<1|1,ooo,val); up(x); } void seg_change(ll x,ll l,ll r,ll val){ if(l>r) return; if(tr[x].f) down(x); if(tr[x].l>=l&&tr[x].r<=r){ tr[x].val+=val; tr[x].f+=val; return ; } ll mid=(tr[x].l+tr[x].r)>>1; if(mid>=l) seg_change(x<<1,l,r,val); if(mid<r) seg_change(x<<1|1,l,r,val); up(x); } int main(){ scanf("%lld",&n); for(ll i=1;i<=n;i++) scanf("%lld%lld%lld",&s[i].a,&s[i].b,&s[i].w),lsh[++cnt]=s[i].a,lsh[++cnt]=s[i].b; sort(lsh+1,lsh+cnt+1); len=unique(lsh+1,lsh+cnt+1)-lsh-1; for(ll i=1;i<=n;i++){ s[i].a=lower_bound(lsh+1,lsh+len+1,s[i].a)-lsh; s[i].b=lower_bound(lsh+1,lsh+len+1,s[i].b)-lsh; } sort(s+1,s+n+1); built(1,1,len); for(ll i=1;i<=n;i++){ if(s[i].a>s[i].b){ maxn=0; seg_max(1,1,s[i].b); change(1,s[i].a,s[i].w+maxn); } else { seg_change(1,s[i].a,s[i].b,s[i].w); maxn=0; seg_max(1,1,s[i].a-1); change(1,s[i].a,s[i].w+maxn); } } maxn=0; seg_max(1,1,len); printf("%lld\n",maxn); }