测试地址:Intervals
题目大意:有一个集合,给定
n
个三元组
[ai,bi,ci]
,表示集合包含区间
[ai,bi]
中的至少
ci
个整数,求这个集合最少可能包含的整数个数。
做法:本题需要用到差分约束系统和单源最长路。
题目中给了形如
∑bik=aitk≥ci
这样的一堆条件,其中
tk
表示
k
在不在集合中,如果在,
tk=1
,否则
tk=0
。我们可以对
t
求一个前缀和,令
Si=∑ik=1tk
,则上面的条件都可以写成
Sbi−Sai−1≥ci
的形式了,这就可以用差分约束系统建图了,从一个新建的源点向其他所有点连一条边权为0的边,然后从原点求一遍单源最长路,
Smax(bi)
的最小值就是它对应顶点的最长路值了,这个值也是要求的答案。如果不明白为什么,建议还是先去了解差分约束系统的定义吧……
等等,好像有什么东西漏了。注意到
ti
的取值并不是任意的,它的取值范围是
0≤ti≤1
,也就是说题目还有隐含的条件:
0≤Si−Si−1≤1
,这个条件可以拆成
Si−Si−1≥0
和
Si−1−Si≥−1
两个条件,那么在原来建的图上再添上这些边,求出来的就是正确的答案了。
有的同学可能会问了,会不会存在无解的情况?可以证明,根据题目的数据范围,建出来的图是不会出现正环的,也就是一定有解,所以不用担心。
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define inf 1000000000
using namespace std;
int n,maxlen=0,s,first[50010]={0},tot=0;
int dis[50010];
bool vis[50010]={0};
struct edge {int v,d,next;} e[300010];
queue <int> Q;
void insert(int a,int b,int d)
{
e[++tot].v=b;
e[tot].d=d;
e[tot].next=first[a];
first[a]=tot;
}
void spfa(int s)
{
Q.push(s);
vis[s]=1;dis[s]=0;
for(int i=0;i<=maxlen+1;i++) dis[i]=-inf;
while(!Q.empty())
{
int v=Q.front();Q.pop();
for(int i=first[v];i;i=e[i].next)
if (dis[e[i].v]<dis[v]+e[i].d)
{
dis[e[i].v]=dis[v]+e[i].d;
if (!vis[e[i].v]) Q.push(e[i].v);
}
vis[v]=0;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
maxlen=max(maxlen,b);
insert(a,b+1,c);
}
s=maxlen+2;
for(int i=0;i<=maxlen;i++)
{
insert(s,i+1,0);
if (i>0)
{
insert(i+1,i,-1);
insert(i,i+1,0);
}
}
spfa(s);
printf("%d",dis[maxlen+1]);
return 0;
}
本文介绍如何使用差分约束系统结合单源最长路算法解决特定区间问题。通过构造图模型,实现对给定区间的整数数量进行有效计算。
593

被折叠的 条评论
为什么被折叠?



