裸的线段树,这里不再讲方程的转移实现,主要证明一下按照和排序的正确性。
对于 \(j\) 我们希望 \(i\) 再其的前面。格式化的,对于 \(a_{i}\leq b_{j}\) 且 \(b_{i}\leq a_{j}\) ,我们期望 \(i\) 排在 \(j\) 的前面。
为什么要 \(b_{i}\) 小于 \(a_{j}\) 呢?
(其实是当其满足大于时, \(i\) 和 \(j\) 的顺序对答案没有影响。)
然后显然的按从小到大排序就好了。
code:
#include <bits/stdc++.h>
#define re register
#define int long long
using namespace std;
const int maxn=200010;
const int INF=1e18;
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1;ch=getchar(); }
while(ch>='0'&&ch<='9') { s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
struct DATE { int a,b,w; int val(){return a+b;} } dat[maxn];
inline bool cmp(DATE as,DATE bs) { return as.val()<bs.val(); }
int n,tot,s[maxn];
#define lid (id<<1)
#define rid (id<<1|1)
struct TREE { int pos,maxl,lazy; } tre[maxn<<2];
inline TREE mx(TREE a,TREE b) { return (a.maxl>=b.maxl)? a:b; }
inline void update(int id) { tre[id]=mx(tre[lid],tre[rid]); }
inline void push_down(int id) {
int s=tre[id].lazy; tre[id].lazy=0;
tre[lid].maxl+=s; tre[rid].maxl+=s;
tre[lid].lazy+=s; tre[rid].lazy+=s;
}
inline TREE query(int id,int l,int r,int ll,int rr) {
if(ll==rr) { if(ll==1) { if(tre[id].lazy) cout<<" wrong "<<endl; } }
if(tre[id].lazy&&l!=r) push_down(id);
if(ll<=l&&r<=rr) { return tre[id]; }
int mid=(l+r)>>1; TREE ans=(TREE){0,0,0};
if(ll<=mid) ans=mx(ans,query(lid,l,mid,ll,rr));
if(rr>mid) ans=mx(ans,query(rid,mid+1,r,ll,rr));
return ans;
}
inline void add(int id,int l,int r,int pos,int val) {
if(tre[id].lazy&&l!=r) push_down(id);
if(l==r) { tre[id].maxl=max(tre[id].maxl,val); return; }
int mid=(l+r)>>1;
if(pos<=mid) add(lid,l,mid,pos,val);
else if(pos>mid) add(rid,mid+1,r,pos,val);
update(id);tre[id].lazy=0;
}
inline void insert(int id,int l,int r,int ll,int rr,int val) {
if(tre[id].lazy&&l!=r) push_down(id);
if(ll<=l&&r<=rr) { tre[id].maxl+=val; tre[id].lazy+=val; return; }
int mid=(l+r)>>1;
if(ll<=mid) insert(lid,l,mid,ll,rr,val);
if(rr>mid) insert(rid,mid+1,r,ll,rr,val);
update(id);tre[id].lazy=0;
}
inline void build(int id,int l,int r) {
if(l==r) { tre[id]=(TREE){l,0,0}; return; }
int mid=(l+r)>>1;
build(lid,l,mid); build(rid,mid+1,r);
update(id); tre[id].lazy=0;
}
signed main(void) {
//freopen("pair.in","r",stdin);
//freopen("cs.txt","w",stdout);
n=read();
for(re int i=1;i<=n;i++) {
dat[i].a=read(); dat[i].b=read(); dat[i].w=read();
s[++tot]=dat[i].a; s[++tot]=dat[i].b;
}
sort(s+1,s+1+tot);
tot=unique(s+1,s+1+tot)-s-1;
for(re int i=1;i<=n;i++) {
dat[i].a=lower_bound(s+1,s+1+tot,dat[i].a)-s;
dat[i].b=lower_bound(s+1,s+1+tot,dat[i].b)-s;
}
sort(dat+1,dat+1+n,cmp); build(1,1,tot);
for(re int i=1;i<=n;i++) {
TREE res=(TREE){0,0,0};
if(dat[i].a<=dat[i].b) {
res=query(1,1,tot,1,dat[i].a);
add(1,1,tot,dat[i].a,res.maxl+dat[i].w);
res=(TREE){0,0,0};
if(dat[i].a+1<=dat[i].b) {
insert(1,1,tot,dat[i].a+1,dat[i].b,dat[i].w);
}
}
else {
res=query(1,1,tot,1,dat[i].b);
add(1,1,tot,dat[i].a,res.maxl+dat[i].w);
}
}
printf("%lld\n",tre[1].maxl);
}