给定 n 个区间 [ai,bi]和 n 个整数 ci。
你需要构造一个整数集合 Z,使得∀i∈[1,n],Z 中满足ai≤x≤bi的整数 x 不少于 ci 个。
求这样的整数集合 Z 最少包含多少个数。
输入格式
第一行包含整数 n。
接下来n行,每行包含三个整数ai,bi,ci。
输出格式
输出一个整数表示结果。
数据范围
1≤n≤50000,
0≤ai,bi≤50000,
1≤ci≤bi−ai+1
输入样例:
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
输出样例:
6
思路
差分约束
分析得,最长路,求最小解,转化成大于等于
dist[i] 到i点包含的整数个数
每个数只能用一次
1.dist(i)-dist(i-1)>=0 到i包含的个数必大于i-1包含的整数个数;
2.dist(i)-dist(i-1)<=1 到i包含的个数最多比i-1包含的整数个数大一 dist(i-1)-dist(i)>=-1;
3.题目要求满足a≤x≤b的整数 x 不少于 c个 dist(b)-dist(a-1)>=ci
a-1因为a≤x 包含a
4.因为a,b可以取到0 ,我们让他们都加1 dist可以更容易的表示 严格一点 数据范围要加1 到50001
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int n;
int h[N],e[N],ne[N],w[N],idx;
void add(int a,int b,int c){
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int dist[N],st[N];//dist[]从1到i包含的数的个数
void spfa(){
memset(dist,-0x3f,sizeof dist);
queue<int> q;q.push(0);dist[0]=0;
while(q.size()){
int t=q.front();q.pop();st[t]=0;
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(dist[j]<dist[t]+w[i]){
dist[j]=dist[t]+w[i];
if(st[j]!=1) q.push(j),st[j]=1;
}
}
}
}
int main(){
cin>>n;
memset(h,-1,sizeof h);
for(int i=1;i<=50001;i++){
add(i-1,i,0);add(i,i-1,-1);
}
for(int i=1;i<=n;i++){
int a,b,c;cin>>a>>b>>c;a++,b++;
add(a-1,b,c);
}
spfa();
cout<<dist[50001];
return 0;
}