题目大意:给定n个区间[li,ri],求一个排列p,元素x若满足至少有一个[lx,rx]中的元素y严格在x前面,就会获得vx的收益。问最大收益。n<=2e5.
题解:考虑x向[lx,rx]连边,那么对于不同的强连通分量,总是能做到排在前面的强连通分量内的点全部获得收益;没有出边的强连通分量总是至少存在一个点没有办法获得收益,钦定是那个最小的点即可。线段树优化建图一下。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
namespace INPUT_SPACE{
const int BS=(1<<24)+5;char Buffer[BS],*HD,*TL;inline int gc() { if(HD==TL) TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);return (HD==TL)?EOF:*HD++; }
inline int inn() { int x,ch;while((ch=gc())<'0'||ch>'9');x=ch^'0';while((ch=gc())>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');return x; }
}using INPUT_SPACE::inn;
const int N=3000000,M=5000000,INF=INT_MAX;
struct edges{
int to,pre;
}e[M];int h[N],etop,v[N],lc[N],rc[N],mn[N],sta[N],dfn[N],low[N],bel[N],out[N],nc,dfc,scc;stack<int> s;
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
inline int build(int &rt,int l,int r)
{
if(!rt) rt=++nc,v[nc]=INF;int mid=(l+r)>>1;if(l==r) return add_edge(rt,l);
return build(lc[rt],l,mid),add_edge(rt,lc[rt]),build(rc[rt],mid+1,r),add_edge(rt,rc[rt]);
}
inline int add(int rt,int l,int r,int s,int t,int x)
{
if(s<=l&&r<=t) return add_edge(x,rt);int mid=(l+r)>>1;
if(s<=mid) add(lc[rt],l,mid,s,t,x);if(mid<t) add(rc[rt],mid+1,r,s,t,x);return 0;
}
inline int tarjan(int x)
{
low[x]=dfn[x]=++dfc,sta[x]=1,s.push(x);
for(int i=h[x],y;i;i=e[i].pre)
if(!sta[y=e[i].to]) tarjan(y),low[x]=min(low[x],low[y]);
else if(sta[y]==1) low[x]=min(low[x],dfn[y]);
if(low[x]==dfn[x])
{
scc++,mn[scc]=v[x],bel[x]=scc,sta[x]=2;int y;
while(s.top()^x) y=s.top(),sta[y]=2,bel[y]=scc,mn[scc]=min(mn[scc],v[y]),s.pop();
s.pop();
}
return 0;
}
int main()
{
int n=inn(),ans=0,rt=0,l,r;nc=n,build(rt,1,n);
rep(i,1,n) l=inn(),r=inn(),v[i]=inn(),add(rt,1,n,l,r,i),ans+=v[i];
rep(i,1,nc) if(!sta[i]) tarjan(i);
rep(x,1,nc) for(int i=h[x];i;i=e[i].pre)
if(bel[e[i].to]^bel[x]) out[bel[x]]++;
rep(i,1,scc) if(!out[i]) ans-=mn[i];return !printf("%d\n",ans);
}