Time limit 2000 ms
Memory limit 65536 kB
You are given n closed, integer intervals [ai, bi] and n integers c1, …, cn.
Write a program that:
reads the number of intervals, their end points and integers c1, …, cn from the standard input,
computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i=1,2,…,n,
writes the answer to the standard output.
Input
The first line of the input contains an integer n (1 <= n <= 50000) – the number of intervals. The following n lines describe the intervals. The (i+1)-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50000 and 1 <= ci <= bi - ai+1.
Output
The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i=1,2,…,n.
题目大意
给定n个闭区间 [ a i , b i ] [a_i,b_i] [ai,bi]和整数 c i c_i ci,要求构造一个正整数集合,使得集合中满足 a i < = x < = b i , i ∈ [ 1 , n ] a_i<=x<=b_i,i\in[1,n] ai<=x<=bi,i∈[1,n]的整数 x x x不少于 c i c_i ci个,求集合最少包含多少个数
题目分析
设
S
i
S_i
Si为集合中区间
[
0
,
i
]
[0,i]
[0,i]内的整数个数
根据题意每个数要么选要么不选
那么有
S
i
−
S
i
−
1
>
=
0
S_i-S_{i-1}>=0
Si−Si−1>=0且
S
i
−
S
i
−
1
<
=
1
S_{i}-S_{i-1}<=1
Si−Si−1<=1
此外n个条件每个形如
S
b
i
−
S
a
i
−
1
>
=
c
i
S_{b_i}-S_{a_i-1}>=c_i
Sbi−Sai−1>=ci
这么看差分约束的模型已经很明显了
根据给出的n个区间确定值域
[
m
i
,
m
x
]
[mi,mx]
[mi,mx]
结点
i
i
i向
i
+
1
i+1
i+1连边,边权为0,结点
i
+
1
i+1
i+1向
i
i
i连边,边权为-1,
i
∈
[
m
i
,
m
x
]
i\in[mi,mx]
i∈[mi,mx]
结点
a
i
−
1
a_i-1
ai−1向
b
i
b_i
bi连边,边权为
c
i
c_i
ci
以 m i mi mi为起点跑最长路,答案为 d i s [ m x ] dis[mx] dis[mx]
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long lt;
#define mkp(x,y) make_pair(x,y)
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return x*f;
}
const int maxn=100010;
int n,m,mi=1e9,mx=-1e9;
struct node{int v,dis,nxt;}E[maxn<<1];
int head[maxn],tot;
int d[maxn],vis[maxn];
void add(int u,int v,int dis)
{
E[++tot].nxt=head[u];
E[tot].v=v; E[tot].dis=dis;
head[u]=tot;
}
void SPFA(int s)
{
queue<int> q; q.push(s);
memset(d,128,sizeof(d)); d[s]=0;
while(!q.empty())
{
int u=q.front(); q.pop();
vis[u]=0;
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v,dis=E[i].dis;
if(d[v]<d[u]+dis)
{
d[v]=d[u]+dis;
if(!vis[v]) q.push(v),vis[v]=1;
}
}
}
}
int main()
{
n=read();
for(int i=1;i<=n;++i)
{
int ai=read(),bi=read(),ci=read();
mx=max(mx,bi); mi=min(mi,ai-1);
add(ai-1,bi,ci);
}
for(int i=mi;i<=mx;++i)
{
add(i,i+1,0);
add(i+1,i,-1);
}
SPFA(mi);
printf("%d",d[mx]);
return 0;
}