Intervals
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 27948 | Accepted: 10763 |
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.
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
Source
考前没几天啦,个人感觉差分约束这类题目还不怎么会那就做几题喽~(条件原因只能写P啦qwq)
题意:一个整数集合Z中有n个区间,每个区间[ai,bi]中至少要有ci个元素,求满足这n个约束的集合最少要有多少个数。
题解:这个很显然啊。我们可以得到这样几个式子:
0<=s[i]-s[i-1]<=1
s[bi]-s[ai-1]>=ci
把符号都转化成大于等于吧,那就变成:
s[i]-s[i-1]>=0
s[i-1]-s[i]>=-1
s[bi]-s[ai-1]>=ci
所以i-1到i建一条权值为0的边,i到i-1建一条权值为-1的边,ai-1到bi建一条权值为ci的边。
然后跑spfa即可la~
附上好丑好丑的代码qwq
pascal变量重名有多难受喔...
var n,min,max,cnt,i,h,t,e,v,u:longint;
dis,vet,next,len,head,vis,a,b,c:array[0..1000000]of longint;
q:array[0..10000000]of longint;
procedure add_edge(u,v,w:longint);
begin
inc(cnt);
vet[cnt]:=v;
next[cnt]:=head[u];
len[cnt]:=w;
head[u]:=cnt;
end;
procedure spfa;
begin
for i:=0 to max do dis[i]:=-1000000000;
dis[min]:=0;q[1]:=min;h:=0;t:=1;vis[min]:=1;
while h<t do
begin
inc(h);
u:=q[h];
e:=head[u];
while e<>-1 do
begin
v:=vet[e];
if dis[v]<dis[u]+len[e] then
begin
dis[v]:=dis[u]+len[e];
if vis[v]=0 then
begin
inc(t);q[t]:=v;
vis[v]:=1;
end;
end;
e:=next[e];
end;
vis[u]:=0;
end;
end;
begin
readln(n);
min:=1000000000;max:=-1000000000;
fillchar(head,sizeof(head),255);
for i:=1 to n do
begin
readln(a[i],b[i],c[i]);
if a[i]-1<min then min:=a[i]-1;
if b[i]>max then max:=b[i];
end;
for i:=1 to n do add_edge(a[i]-1,b[i],c[i]);
for i:=min to max do
begin
add_edge(i-1,i,0);
add_edge(i,i-1,-1);
end;
spfa();
writeln(dis[max]);
end.
备注一下,上面的方法是转化为大于等于跑最长路的方法(个人较为习惯),下面贴小于等于跑最短路的代码吧,避免误解,两种方法都是可以的啦~
var n,min,max,cnt,i,h,t,e,v,u:longint; dis,vet,next,len,head,vis,a,b,c:array[0..1000000]of longint; q:array[0..10000000]of longint; procedure add_edge(u,v,w:longint); begin inc(cnt); vet[cnt]:=v; next[cnt]:=head[u]; len[cnt]:=w; head[u]:=cnt; end; procedure spfa; begin for i:=min to max do dis[i]:=1000000000; dis[max]:=0;q[1]:=max;h:=0;t:=1;vis[max]:=1; while h<t do begin inc(h); u:=q[h]; e:=head[u]; while e<>-1 do begin v:=vet[e]; if dis[v]>dis[u]+len[e] then begin dis[v]:=dis[u]+len[e]; if vis[v]=0 then begin inc(t);q[t]:=v; vis[v]:=1; end; end; e:=next[e]; end; vis[u]:=0; end; end; begin readln(n); min:=1000000000;max:=-1000000000; fillchar(head,sizeof(head),255); for i:=1 to n do begin readln(a[i],b[i],c[i]); if a[i]<min then min:=a[i]; if b[i]+1>max then max:=b[i]+1; end; for i:=1 to n do add_edge(b[i]+1,a[i],-c[i]); for i:=min to max-1 do begin add_edge(i+1,i,0); add_edge(i,i+1,1); end; spfa(); writeln(-dis[min]); end.