差分约束。
限制条件可以转化成不等关系。设 s i s_i si 表示 i i i 的前缀和,显然有 s R − s L − 1 ≥ C s_R-s_{L-1}\geq C sR−sL−1≥C。又因为每个相邻的前缀和至多差 1 1 1 至少差 0 0 0,即 0 ≤ s R − s R − 1 ≤ 1 0\leq s_R-s_{R-1}\leq 1 0≤sR−sR−1≤1,所以有总式:
{ s R − s L − 1 ≥ C s R − s R − 1 ≥ − 1 s R − s R − 1 ≥ 0 \begin{cases} s_R-s_{L-1}\geq C\\ s_R-s_{R-1}\geq -1\\ s_R-s_{R-1}\geq 0 \end{cases} ⎩ ⎨ ⎧sR−sL−1≥CsR−sR−1≥−1sR−sR−1≥0
直接差分约束跑最长路即可。
注意最后的终点不是 N N N,而是 R max R_{\max} Rmax。
cpp
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=3e4+5;
int head[maxn],cnt,dis[maxn];
struct edge{int to,nxt,w;}e[maxn];
bool vis[maxn];
void add(int x,int y,int z){e[++cnt]={y,head[x],z},head[x]=cnt;}
void spfa(int s)
{
queue<int> q;
q.push(s),dis[s]=0,vis[s]=1;
while(!q.empty())
{
int x=q.front();q.pop();vis[x]=0;
for(int i=head[x];i;i=e[i].nxt)
if(dis[e[i].to]<dis[x]+e[i].w)
{
dis[e[i].to]=dis[x]+e[i].w;
if(!vis[e[i].to]) q.push(e[i].to),vis[e[i].to]=1;
}
}
}
signed main()
{
int N;cin>>N;
int mxr=N;
for(int i=1,L,R,C;i<=N;i++) cin>>L>>R>>C,add(L-1,R,C),mxr=max(mxr,R);
for(int i=1;i<=mxr;i++) add(i,i-1,-1),add(i-1,i,0);
for(int i=1;i<=mxr;i++) dis[i]=-INT_MAX;
spfa(0);
cout<<dis[mxr];
return 0;
}