362. 区间

题目链接

362. 区间

给定 \(n\) 个区间 \([a_i,b_i]\)\(n\) 个整数 \(c_i\)

你需要构造一个整数集合 \(Z\),使得 \(\forall i \in [1,n]\)\(Z\) 中满足 \(a_i \le x \le b_i\) 的整数 \(x\) 不少于 \(c_i\) 个。

求这样的整数集合 \(Z\) 最少包含多少个数。

输入格式

第一行包含整数 \(n\)

接下来 \(n\) 行,每行包含三个整数 \(a_i,b_i,c_i\)

输出格式

输出一个整数表示结果。

数据范围

\(1 \le n \le 50000\),
\(0 \le a_i,b_i \le 50000\),
\(1 \le c_i \le b_i-a_i+1\)

输入样例:

5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1

输出样例:

6

解题思路

差分约束

\(x[i]\) 表示 \(i\) 这个数是否选了,则有 \(0\leq x[i]\leq 1\)\(s[i]\) 为其前缀和,要求 \(a\sim b\) 中的数不少于 \(c\) 个,即 \(s[b]-s[a]\geq c\),另外前缀和有 \(s[i]\leq s[i+1]\),由于是前缀和,而 \(a,b\) 可能为 \(0\),则所有的 \(a,b\) 都需要右移一位,根据这些不等式差分约束,求最小值即求解最长路,最后 \(s[50001]\) 即为答案

  • 时间复杂度:\(O(kn)\)

代码

// Problem: 区间
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/364/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=50005;
int n,d[N];
bool v[N];
vector<PII> adj[N];
void spfa()
{
	memset(d,-0x3f,sizeof d);
	queue<int> q;
	q.push(0);
	d[0]=0,v[0]=true;
	while(q.size())
	{
		int x=q.front();
		q.pop();
		v[x]=false;
		for(auto t:adj[x])
		{
			int y=t.fi,w=t.se;
			if(d[y]<d[x]+w)
			{
				d[y]=d[x]+w;
				if(!v[y])v[y]=true,q.push(y);
			}
		}
	}
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
    	int a,b,c;
    	cin>>a>>b>>c;
    	a++,b++;
    	adj[a-1].pb({b,c});
    }
    for(int i=1;i<=50001;i++)
    	adj[i].pb({i-1,-1}),adj[i-1].pb({i,0});
    spfa();
    cout<<d[50001];
    return 0;
}
posted @ 2022-08-12 17:20  zyy2001  阅读(13)  评论(0编辑  收藏  举报