POJ - 1201 Intervals【差分约束】

Time limit 2000 ms
Memory limit 65536 kB

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.


题目大意

给定n个闭区间 [ a i , b i ] [a_i,b_i] [ai,bi]和整数 c i c_i ci,要求构造一个正整数集合,使得集合中满足 a i &lt; = x &lt; = b i , i ∈ [ 1 , n ] a_i&lt;=x&lt;=b_i,i\in[1,n] ai<=x<=bi,i[1,n]的整数 x x x不少于 c i c_i ci个,求集合最少包含多少个数


题目分析

S i S_i Si为集合中区间 [ 0 , i ] [0,i] [0,i]内的整数个数
根据题意每个数要么选要么不选
那么有 S i − S i − 1 &gt; = 0 S_i-S_{i-1}&gt;=0 SiSi1>=0 S i − S i − 1 &lt; = 1 S_{i}-S_{i-1}&lt;=1 SiSi1<=1
此外n个条件每个形如 S b i − S a i − 1 &gt; = c i S_{b_i}-S_{a_i-1}&gt;=c_i SbiSai1>=ci

这么看差分约束的模型已经很明显了
根据给出的n个区间确定值域 [ m i , m x ] [mi,mx] [mi,mx]
结点 i i i i + 1 i+1 i+1连边,边权为0,结点 i + 1 i+1 i+1 i i i连边,边权为-1, i ∈ [ m i , m x ] i\in[mi,mx] i[mi,mx]
结点 a i − 1 a_i-1 ai1 b i b_i bi连边,边权为 c i c_i ci

m i mi mi为起点跑最长路,答案为 d i s [ m x ] dis[mx] dis[mx]


#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long lt;
#define mkp(x,y) make_pair(x,y)

int read()
{
    int f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return x*f;
}

const int maxn=100010;
int n,m,mi=1e9,mx=-1e9;
struct node{int v,dis,nxt;}E[maxn<<1];
int head[maxn],tot;
int d[maxn],vis[maxn];

void add(int u,int v,int dis)
{
	E[++tot].nxt=head[u];
	E[tot].v=v; E[tot].dis=dis;
	head[u]=tot; 
}

void SPFA(int s)
{
	queue<int> q; q.push(s);
	memset(d,128,sizeof(d)); d[s]=0;
	
	while(!q.empty())
	{
		int u=q.front(); q.pop(); 
		vis[u]=0;
		for(int i=head[u];i;i=E[i].nxt)
		{
			int v=E[i].v,dis=E[i].dis;
			if(d[v]<d[u]+dis)
			{
				d[v]=d[u]+dis;
				if(!vis[v]) q.push(v),vis[v]=1;
			}
		}
	}
}

int main()
{
	n=read();
	
	for(int i=1;i<=n;++i)
	{
		int ai=read(),bi=read(),ci=read();
		mx=max(mx,bi); mi=min(mi,ai-1);
		add(ai-1,bi,ci); 
	}
	
	for(int i=mi;i<=mx;++i)
	{
		add(i,i+1,0);
		add(i+1,i,-1);
	}
	
	SPFA(mi);
	printf("%d",d[mx]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值