Description
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.
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.
题目大意:
给出n个闭区间[ai,bi],每个区间对应一个ci,表示集合Z在区间[ai,bi]内至少有ci个相同元素,问集合Z至少有几个元素。每个测试点有多组输入数据每组第一行为n (1 <= n <= 50000)。接下来n行,每行给出一组ai,bi,ci。(0 <= ai <= bi <= 50000,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.
要求输出集合Z中最少有几个元素,题目保证有解。
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
题解
差分约束系统。最近恶补知识面,看清北学堂2013年noip的视频时,想起来要做点题练练了。
首先从视频上对差分约束系统大致的认识是:将题目给出不等式作为最短(长)路的限制条件,跑最短(长)路,当有负环时无解。
可是这道题没给我们不等式,但有“最小”这个条件,所以用Si表示区间[0,i]区间内至少有多少个元素的话,那么Sbi - Sai >= ci。可转换为Sbi>= Sai+ci,这可作为跑最长路的限制条件了。可是这样50000个点只连了少量边,可能跑不出我们想要的最短路。为了保险,还有一个式子:0<=Si - Si-1<=1,这样就能跑最长路了。因为题目保证有解,所以不用判负环。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
#define inf 1<<30
using namespace std;
int n,head[50005],zz,S,T;
struct bian{int to,nx,v;} e[200002];
int dis[50005],pd[50005],q[50005];
void insert(int x,int y,int z)
{
zz++; e[zz].to=y; e[zz].v=z; e[zz].nx=head[x]; head[x]=zz;
}
void init()
{
memset(head,0,sizeof(head));
zz=0; S=inf; T=-inf;
int i,a,b,c;
for(i=1;i<=n;i++)
{scanf("%d%d%d",&a,&b,&c);
insert(a,b+1,c);
//因为a>=0,为了让a-1不超界,所以将所有点向正方向平移一位
S=min(S,a); T=max(T,b+1);
}
for(i=S;i<T;i++)
{insert(i,i+1,0); insert(i+1,i,-1);}
}
void spfa()
{
int t=0,w=1,i,p;
for(i=S;i<=T;i++) {dis[i]=-inf; pd[i]=0;}
dis[S]=0; pd[S]=1; q[t]=S;
while(t!=w)
{p=q[t];
t=(t+1)%50003;
for(i=head[p];i;i=e[i].nx)
{if(dis[e[i].to]<dis[p]+e[i].v)
{dis[e[i].to]=dis[p]+e[i].v;
if(!pd[e[i].to])
{pd[e[i].to]=1; q[w]=e[i].to; w=(w+1)%50003;}
}
}
pd[p]=0;
}
printf("%d\n",dis[T]);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{init(); spfa();}
return 0;
}