Intervals
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 26192 | Accepted: 10015 |
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
很有收获的一道题,感觉对差分约束的理解更深了一点。
题意:平面上有n个区间,第i个区间的左端点为ai,右端点为bi。然后求一个最短长度的集合z,使该集合在每一个区间[ai,bi],都至少有ci个点在区间中。求z集合的长度。
思路:一开始的思路是贪心,很明显可以将区间按右端点排序,然后每个区间就从最右边开始选m个点(m为ci - 该区间已经被选的点的个数,m<=0时,则该区间可以不选。)。优化可以用一个线段树或树状数组维护。
但既然是在学差分约束,当然还是用差分约束系统来做。
开始一直没有思路,因为我以前遇见的都是求最大值,最小值并不知道怎么入手。
然后看了网上的一个博客,才知道:
求最大值: 方程变形为: a - b <= c ,b->a,权边为c。 求最短路
求最小值: 方程变形为: b - a >= -c,a->b,权边为-c。求最长路
然后还有一个关键点在于,如果要得到正确答案,必须保证相邻点连通。
因为:
0 <= a[i+1] - a[i] <= 1
然后两点之间加两条边即可。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include<cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <cctype>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 50000 + 100;
const int INF = 1e8;
struct P{
int v,w,next;
}G[maxn*20];
int head[maxn],out[maxn],dis[maxn],vis[maxn];
int n,tot;
void init(void){
tot = 0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w){
G[tot].v = v;
G[tot].w = w;
G[tot].next = head[u];
head[u] = tot++;
}
int spfa(int st,int ed){
queue<int> que;
for(int i=0 ;i<=ed ;i++){
dis[i] = -INF;
vis[i] = 0;
out[i] = 0;
}
dis[st] = 0;
vis[st] = 1;
que.push(st);
while(que.size()){
int u = que.front();
que.pop();
vis[u] = 0;
for(int i=head[u] ;i!=-1 ;i=G[i].next){
int v = G[i].v,w = G[i].w;
if(dis[u] + w > dis[v]){
dis[v] = dis[u] + w;
if(!vis[v]){
vis[v] = 1;
que.push(v);
}
}
}
}
return dis[ed];
}
void solve(int u,int v){
printf("%d\n",spfa(u,v));
}
int main(){
while(scanf("%d",&n) != EOF){
init();
int a,b,c;
int u=maxn,v=0;
while(n--){
scanf("%d%d%d",&a,&b,&c);
add(a,b+1,c);
u = min(u,a);
v = max(v,b+1);
}
for(int i=0 ;i<=v ;i++){
add(i+1,i,-1);
add(i,i+1,0);
}
solve(u,v);
}
return 0;
}