差分约束 - Intervals - POJ 1201
题意:
给 定 n 个 区 间 [ a i , b i ] 和 n 个 整 数 c i 。 给定 n 个区间 [a_i,b_i]和 n 个整数 c_i。 给定n个区间[ai,bi]和n个整数ci。
你 需 要 构 造 一 个 整 数 集 合 Z , 使 得 ∀ i ∈ [ 1 , n ] , Z 中 满 足 a i ≤ x ≤ b i 的 整 数 x 不 少 于 c i 个 。 你需要构造一个整数集合 Z,使得∀i∈[1,n],Z 中满足a_i≤x≤b_i的整数 x 不少于 c_i 个。 你需要构造一个整数集合Z,使得∀i∈[1,n],Z中满足ai≤x≤bi的整数x不少于ci个。
求 这 样 的 整 数 集 合 Z 最 少 包 含 多 少 个 数 。 求这样的整数集合 Z 最少包含多少个数。 求这样的整数集合Z最少包含多少个数。
输入格式
第 一 行 包 含 整 数 n 。 第一行包含整数 n。 第一行包含整数n。
接 下 来 n 行 , 每 行 包 含 三 个 整 数 a i , b i , c i 。 接下来n行,每行包含三个整数a_i,b_i,c_i。 接下来n行,每行包含三个整数ai,bi,ci。
输出格式
输 出 一 个 整 数 表 示 结 果 。 输出一个整数表示结果。 输出一个整数表示结果。
数据范围
1 ≤ n ≤ 50000 , 0 ≤ a i , b i ≤ 50000 , 1 ≤ c i ≤ b i − a i + 1 1≤n≤50000, 0≤a_i,b_i≤50000, 1≤c_i≤b_i−a_i+1 1≤n≤50000,0≤ai,bi≤50000,1≤ci≤bi−ai+1
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
分析:
本 题 是 求 最 小 值 , 故 跑 最 长 路 。 本题是求最小值,故跑最长路。 本题是求最小值,故跑最长路。
在 某 段 区 间 中 计 数 , 考 虑 前 缀 和 的 思 想 。 在某段区间中计数,考虑前缀和的思想。 在某段区间中计数,考虑前缀和的思想。
S i 表 示 大 小 介 于 区 间 [ 0 , i ] 的 数 的 个 数 。 S_i表示大小介于区间[0,i]的数的个数。 Si表示大小介于区间[0,i]的数的个数。
则 介 于 区 间 [ a , b ] 的 数 的 个 数 为 S b − S a − 1 。 则介于区间[a,b]的数的个数为S_b-S_{a-1}。 则介于区间[a,b]的数的个数为Sb−Sa−1。
有 约 数 不 等 式 组 : 有约数不等式组: 有约数不等式组:
{ 0 ≤ S i − S i − 1 ≤ 1 , 即 第 i 个 数 选 或 不 选 < = > S i ≥ S i − 1 和 S i − 1 ≥ S i − 1 , ① S b i − S a i − 1 ≥ c i , 即 区 间 [ a i , b i ] 中 数 的 个 数 不 少 于 c i 个 < = > S b i ≥ S a i − 1 + c i ② \begin{cases}0≤S_i-S_{i-1}≤1,即第i个数选或不选\quad<=>\quad S_i≥S_{i-1}和S_{i-1}≥S_i-1,\qquad\quad①\\\\S_{b_i}-S_{a_{i}-1}≥c_i,即区间[a_i,b_i]中数的个数不少于c_i个\quad<=>\quad S_{b_i}≥S_{a_i-1}+c_i\quad②\end{cases} ⎩⎪⎨⎪⎧0≤Si−Si−1≤1,即第i个数选或不选<=>Si≥Si−1和Si−1≥Si−1,①Sbi−Sai−1≥ci,即区间[ai,bi]中数的个数不少于ci个<=>Sbi≥Sai−1+ci②
由 约 束 条 件 ① , 我 们 需 要 建 立 i − 1 − > i 的 边 , 由约束条件①,我们需要建立i-1->i的边, 由约束条件①,我们需要建立i−1−>i的边,
这 样 , 我 们 以 编 号 最 小 的 点 作 为 源 点 , 就 能 够 遍 历 到 剩 下 所 有 的 点 和 边 。 这样,我们以编号最小的点作为源点,就能够遍历到剩下所有的点和边。 这样,我们以编号最小的点作为源点,就能够遍历到剩下所有的点和边。
为 了 便 于 前 缀 和 的 使 用 , 我 们 将 区 间 整 体 向 右 平 移 一 个 单 位 , 再 把 0 号 点 作 为 源 点 , 跑 最 长 路 即 可 。 为了便于前缀和的使用,我们将区间整体向右平移一个单位,再把0号点作为源点,跑最长路即可。 为了便于前缀和的使用,我们将区间整体向右平移一个单位,再把0号点作为源点,跑最长路即可。
a i 和 b i 的 范 围 在 [ 1 , 50001 ] 之 间 , 最 后 我 们 输 出 d i s [ 50001 ] 即 答 案 。 a_i和b_i的范围在[1,50001]之间,最后我们输出dis[50001]即答案。 ai和bi的范围在[1,50001]之间,最后我们输出dis[50001]即答案。
代码:
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N=50010, M=150010;
int n;
int e[M],ne[M],w[M],h[N],idx;
int dis[N];
bool st[N];
void add(int a,int b,int c)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void spfa()
{
memset(dis,-0x3f,sizeof dis);
memset(st,false,sizeof st);
queue<int> Q;
Q.push(0);
st[0]=true;
dis[0]=0;
while(Q.size())
{
int u=Q.front();
Q.pop();
st[u]=false;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(dis[j]<dis[u]+w[i])
{
dis[j]=dis[u]+w[i];
if(!st[j])
{
st[j]=true;
Q.push(j);
}
}
}
}
}
int main()
{
scanf("%d",&n);
memset(h,-1,sizeof h);
for(int i=1;i<=50001;i++) add(i-1,i,0),add(i,i-1,-1);
int a,b,c;
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
a++,b++;
add(a-1,b,c);
}
spfa();
printf("%d\n",dis[50001]);
return 0;
}