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.
Sample Input
5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1
Sample Output
6
题意:一共n个区间,要求找一个集合x,至少含有每个区间[ li , ri ] 元素个数为wi
求集合x的含有最少元素的个数
思路:设dis [ x ] 为区间 [0,x )含有的元素个数
对于每个区间 [ u , v ] 至少有w个元素
则有关系 dis [ v + 1 ] - dis [ u ] >=w;
------------> dis [ v + 1 ] >= dis[ u ] + w;
可以建一条从 u 到 v+1 权值为 w 的边
对于每个dis [i] 有 dis [ i ] - dis [ i - 1 ] >=0 且 dis [ i ] - dis [ i - 1 ] <= 1
---------------------> dis [ i ] >= dis [ i - 1 ] 0 且 dis [ i - 1 ] >= dis[ i ] - 1
可以建一条从 i-1 到 i 权值为 0 的边
可以建一条从 i 到 i - 1 权值为 - 1的边
最后跑一下,最长路
代码:
#include<cstdio>
#include<cstring>
#include<queue>
#define Inf 0x3f3f3f3f
using namespace std;
const int N = 50005;
struct node{
int v,w;
int next;
}edge[N*10];
int head[N],id;
int dis[N],vis[N],n;
void init(){
id=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w){
edge[id].v=v;
edge[id].w=w;
edge[id].next=head[u];
head[u]=id++;
}
void SPFA(int s,int t){
memset(dis,-Inf,sizeof(dis));
memset(vis,0,sizeof(vis));
queue<int>p;
p.push(s);
dis[s]=0;
vis[s]=1;
while(!p.empty()){
int u=p.front();
p.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
int w=edge[i].w;
if(dis[v]<dis[u]+w){
dis[v]=dis[u]+w;
if(!vis[v]){
p.push(v);
vis[v]=1;
}
}
}
}
printf("%d\n",dis[t]);
}
int main(){
while(~scanf("%d",&n)){
init();
int l=Inf,r=-Inf;
for(int i=0;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v+1,w);
l=min(l,u);
r=max(r,v+1);
}
for(int i=l;i<=r;i++){
add(i,i-1,-1);
add(i-1,i,0);
}
SPFA(l,r);
}
return 0;
}