题面:
给定 n 个闭区间[ai,bi]和n 个整数ci。你需要构造一个整数集合 Z,使得对于任意 i∈[1,n],Z 中满足ai≤x≤bi 的整数xx 不少于 ci个,求这样的整数集合 Z 最少包含多少个数。
简而言之就是,从0∼5e4中选出尽量少的整数,使每个区间 [ai,bi] 内都有至少 ci个数被选出。
对于全部数据,1≤n≤5e4,0≤ai≤bi≤5e4,1≤ci≤bi−ai+1
///
此题状态定义就不好想;
可以关注到区间的特性,用s[i] 表示0~i所需最小个数
翻译:s[b]-s[a-1]>=c;
到这个地方就有差分约束的味道了
进一步思考,不同的(无论相交与否)的区间是有联系的,而就这一个差分约束条件显然无法建立联系
这个时候需要用一种显然的关系把每一个区间的端点值联系起来,完成建图
1.数字区间是连续的,每一个数字都应该被包含进来,2. 关系应该从s[i]和s[i-1]之间建立。
可以想到:
1.s[i]-s[i-1]>=-0;
2.s[i]-s[i-1]<=1 -------- s[i-1]-s[i]>=-1;
所以连边跑最长路即可(数据规模保证此题有解,不会出现正环)
(注意起点是“-1”,数据规模上 a>=0,a可以取0,还要处理起点)
、、、也可以用贪心等方法过
#include<bits/stdc++.h>
using namespace std;
//此题注意0也在讨论范围内
//所以起点是-1
//s[i] 0~i最小取的个数
//s[k]-s[k-1]>=0
//s[k-1]-s[k]>=-1
//s[b]-s[a-1]>=c
const int maxn=5e5+10;
struct road{
int v,w,nxt;
}r[maxn];
int head[maxn],cnt=0;
inline void _add(int u,int v,int w){
r[++cnt].v=v,r[cnt].w=w,r[cnt].nxt=head[u],head[u]=cnt;
}
int dis[maxn];
bool vis[maxn];
int st=5e4+2;
inline void spfa(){
memset(dis,-127,sizeof dis);
queue<int>q;
dis[st]=0;
q.push(st);
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=0;
for(int i=head[u];i;i=r[i].nxt){
int v=r[i].v,w=r[i].w;
if(dis[v]<dis[u]+w){
dis[v]=dis[u]+w;
if(!vis[v])q.push(v);
vis[v]=1;
}
}
}
}
int n;
signed main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
_add(a-1,b,c);
}
_add(st,0,0);_add(0,st,-1);
for(int i=0;i<=5e4;++i){
_add(i,i+1,0);_add(i+1,i,-1);
}
spfa();
printf("%d",dis[50000]);
return 0;
}