题解
算是历史遗留问题的解决
之前队长快跑看题解很迷糊,觉得似懂非懂的,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);
}
