这道题,emm裸的差分约束,我们不妨定义s[i]表示0~i最少选多少个数,那么由题意给的ai~bi不少于ci个,因为[ai~bi]是闭区间,那么我们就可以列出来s[bi]-s[ai-1]>=ci,这样一个差分约束的框架就形成了,但是不能保证结果,所以我们要再附加一些条件1.s[i]-s[i-1]<=1,s[i]-s[i-1]>=0,然后我们就可以愉快的跑一下单源最长路,输出结果就好了(dis[maxa]]我们要记录区间的最左和最右)
代码(2000ms 卡过)
//By AcerMo
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 0x7fffffff
using namespace std;
int n,maxn,minn,m;
struct edge
{
int v,len;
}now;
vector<edge>v[51001];
bool vis[51001];
int dis[51001];
inline void SPFA()
{
queue<int>q;q.push(minn-1);
vis[minn-1]=1,dis[minn-1]=0;
while(!q.empty())
{
int u=q.front();q.pop();vis[u]=0;
for(int j=0;j<v[u].size();j++)
{
int go=v[u][j].v;
int pay=v[u][j].len;
if(dis[go]<dis[u]+pay)
{
dis[go]=dis[u]+pay;
if(!vis[go])
vis[go]=1,q.push(go);
}
}
}
return (void)(printf("%d\n",dis[maxn]));
}
inline int read()
{
int x=0;char ch=getchar();
while (ch>'9'||ch<'0') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline void add(int a,int b,int c)
{
now.v=b;now.len=c;v[a].push_back(now);
return ;
}
int main()
{
for (int i=0;i<=50001;i++) dis[i]=-INF;
while(scanf("%d",&m)!=EOF)
{
minn=INF,maxn=0;
for (int i=1;i<=m;i++)
{
int u=read(),x=read(),len=read();
maxn=max(maxn,x);minn=min(minn,u);
add(u-1,x,len);
}
for(int i=minn;i<=maxn;i++)
add(i,i-1,-1),add(i-1,i,0);
SPFA();
for(int i=0;i<=maxn;i++)
v[i].clear(),dis[i]=-INF;
}
return 0;
}