Intervals
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 24948 | Accepted: 9491 |
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
差分约束的区间约束问题。
题意:给定n(n <= 50000)个整点闭区间和这个区间中至少有多少整点需要被选中,每个区间的范围为[ai, bi],并且至少有ci个点需要被选中,其中0 <= ai <= bi <= 50000,问[0, 50000]至少需要有多少点被选中。
题解:这个题的话是典型的差分约束问题,s[i]代表 [0,i]区间内有多少被选中,所以d[i] - d[j-1] >= w ,但是由于 j是从 0 开始,所以下标要+1,还有就是对于某个区间 [i,i],0<=s[i+1]-s[i]<=1,这样的话根据约束条件就可以求出s->t的最长路即是最后的结果。
差分约束不等式的标准化:
如果给出的不等式有"<="也有">=",又该如何解决呢?很明显,首先需要关注最后的问题是什么,如果需要求的是两个变量差的最大值,那么需 要将所有不等式转变成"<="的形式,建图后求最短路;相反,如果需要求的是两个变量差的最小值,那么需要将所有不等式转化成">=",建图 后求最长路。
如果有形如:A - B = c 这样的等式呢?我们可以将它转化成以下两个不等式:
A - B >= c (1)
A - B <= c (2)
再通过上面的方法将其中一种不等号反向,建图即可。 最后,如果这些变量都是整数域上的,那么遇到A - B < c这样的不带等号的不等式,我们需要将它转化成"<="或者">="的形式,即 A - B <= c - 1。
#include <iostream> #include <cstdio> #include <string.h> #include <queue> #include <algorithm> #include <math.h> using namespace std; typedef long long LL; const int INF = 999999999; const int N = 160000; const int M = 50005; int n; struct Edge{ int v,w,next; }edge[N]; int head[M]; int tot; void init(){ memset(head,-1,sizeof(head)); tot = 0; } void addEdge(int u,int v,int w,int &k){ edge[k].v = v,edge[k].w = w,edge[k].next = head[u],head[u] = k++; } bool vis[M]; int low[M]; int spfa(int s,int t){ for(int i=s;i<=t;i++){ vis[i] = false; low[i] = -INF; ///求最长路初始值应该是 -INF } queue<int> q; low[s] = 0; q.push(s); while(!q.empty()){ int u = q.front(); q.pop(); vis[u] = false; for(int k=head[u];k!=-1;k=edge[k].next){ int v = edge[k].v,w = edge[k].w; if(low[v]<low[u]+w){ low[v] = low[u]+w; if(!vis[v]){ vis[v] = true; q.push(v); } } } } return low[t]-low[s]; } int main(){ while(scanf("%d",&n)!=EOF){ init(); int MIN = INF,MAX = -1; for(int i=1;i<=n;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); MAX = max(MAX,v+1); MIN = min(MIN,u); addEdge(u,v+1,w,tot); } // printf("%d %d ",MIN,MAX); for(int i=MIN;i<MAX;i++){ addEdge(i,i+1,0,tot); addEdge(i+1,i,-1,tot); } printf("%d ",spfa(MIN,MAX)); } return 0; }