You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.
Write a program that:
> reads the number of intervals, their endpoints 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 <= 50 000) - 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 <= 50 000 and 1 <= ci <= bi - ai + 1.
Process to the end of file.
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.
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
【题解】通过观察发现,这道题目就是再求每个位置上是0 还是 1 。
而题目的信息点之间具有一些不等式:
设数组s[],表示第i 个数以前包括i 有多少个1;
得 s[ i ]-s[i-1]>=0;s[i]>=s[i-1]+0;
s[i-1]-s[i]>=-1; s[i-1]>=s[i]-1;
s[ b[ i ] ]-s[ a[ i ] ]>=c[ i ] ---> s[ b[ i ] ]>=s[ a[ i ] ]+c[ i ]; 所以这就是差分约束,这些不等式就是spfa 的比较方式,也就是说做一遍spfa 就可以让 s[] 数组的值做这些 “松弛” 操作,最后得到的 s[ n ] 就是所求值。
下面附上代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define maxn 51000
#define maxm 200000
#define inf 2147483641
int tot,edge[maxm],s[maxn],twice[maxn],to[maxm],next[maxm],d[maxn],f[maxn*200],n;
inline void add(int x,int y,int z){
edge[++tot]=z;to[tot]=y;next[tot]=s[x];s[x]=tot;
}
inline void spfa(int x)
{
memset(d,0x7f,sizeof(d));
memset(twice,0,sizeof(twice));
int head=1,tail=1;d[x]=0;
f[1]=x;twice[x]=1;
while(head<=tail){
int id=f[head++];
twice[id]=0;
for(int i=s[id];i;i=next[i])
if(d[to[i]]>d[id]+edge[i]){
d[to[i]]=d[id]+edge[i];
if(!twice[to[i]]){
twice[to[i]]=1;
f[++tail]=to[i];
}
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF){
int maxx=0,minx=50005;tot=0;
memset(s,0,sizeof(s));
for(int i=1,a,b,c;i<=n;i++){
scanf("%d%d%d",&a,&b,&c);
a++;b++;
if(a<minx)minx=a;
if(b>maxx)maxx=b;
add(a-1,b,-c);
}
int v0=minx-1;add(v0,minx,0);
for(int i=minx;i<=maxx;i++){
add(i,i+1,0);
add(i,i-1,1);
}
spfa(v0);
printf("%d\n",-d[maxx+1]);
}
return 0;
}