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.
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.
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.
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
6
有一段数,1~N,让你从这N个数中选择ans个。输入N个区间,要求满足每个区间至少包含Ci个被选择的数。输出最小ans。
差分约束
这题是POJ 1716 Integer Intervals(贪心or差分约束)的加强版
POJ 1716要求的每个区间要至少有2个不同的数被选择,而本体是要求输入的Ci个
POJ 1716 Integer Intervals(贪心or差分约束)题解可见我的上一篇博客
我的POJ 1716 Integer Intervals题解
其实只需要改上篇博客的一个地方就行,把输入建边的 v+1,u,-2改为v+1,u,-Ci(逃)
设a[i]为从起点到第i个点选择了多少个数
所以对于输入的区间【left,right】有a[right]-a[left-1]>=Ci
因为left>=0,为了方便处理负数,可以左右端点统一 +1,上式等价a[right+1]-a[left]>=Ci
但是只有N个区间给出的关系还是不能建图
所以还有以下隐含关系
a[i+1]-a[i]>=0
a[i+1]=a[i]<=1
之后就可以建图,跑一边最短路 spfa 即可
通过上面三个关系,可以如下方式具体建边(单向边)
right+1,left,-Ci
i,i+1,1
i+1,i,0
AC代码
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define maxn 50010
#define maxm 210
int tot,ma,mi;
int head[maxn],dis[maxn];
bool vis[maxn];
typedef struct node{
int v,nex,w;
}node;
node e[maxn+maxn+maxn];
void add(int u,int v,int w)
{
e[tot].v=v;
e[tot].w=w;
e[tot].nex=head[u];
head[u]=tot++;
}
void spfa()
{
//printf("ans:\n");
for(int i=0;i0;
}
dis[ma]=0;
queue<int>q;
q.push(ma);
while(!q.empty()){
int v,u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i!=-1;i=e[i].nex){
v=e[i].v;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!vis[v]){
q.push(v);
vis[v]=true;
}
}
}
}
printf("%d\n",abs(dis[mi]-dis[ma]));
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF){
tot=0;
mi=inf;
ma=-inf;
memset(head,-1,sizeof(head));
int i,l,r,w;
for(i=0;iscanf("%d%d%d",&l,&r,&w);
mi=min(mi,l);
ma=max(ma,r+1);
add(r+1,l,-w);
}
for(i=0;i1,1);
add(i+1,i,0);
}
spfa();
}
return 0;
}