传送门 >Here<

题意:给出N段区间,并告诉你每段区间里有几个数(一个位置只能放一个数) 问总共至少有几个数

解题思路

  差分约束题,本蒟蒻也是第一次做差分约束题……

  所谓差分约束,常常是通过最短路(或最长路)来解决一些约束问题,例如不等式组

  举个例子:$$x1 -x2 \leq a1 (1)$$$$x2 -x3 \leq a2 (2)$$$$x1 -x3 \leq a3 (3)$$求解$x1-x3$的解集

  则我们可以让1~2连一条长度为a1的有向边,2~3连一条长度为a2的有向边,1~3连一条长度为a3的有向边

  我们会发现$(1)+(2)$可以得到$x1 - x3 \leq a1 + a2$(利用了不等式之间相加的定理),因此得到一组不等式组$$x1 - x3 \leq a1 + a2$$$$x1 -x3 \leq a3 (3)$$

  而最终由于是小于等于的约数,解集应当取$Min\{ a1+a2, a3 \}$

  为什么可以转化为最短路问题呢?考虑一条路径,对于所有非起点且非终点的点,与其相邻的路径上的两个点对应了两条路径,不妨设为$a-s,s-b$,则当这两个不等式相加时,中介点$s$一定会被消掉。宏观来看,一条路径上所有非起点终点的点都将为被抵消掉。因此最后只剩下路径的头尾了。而要求解集,如果是$<$,则应该取最小值,也就是最短路了。

  以上是差分约束的基本概念。那么回到这道题来,好像和差分约束没什么关系?

  光看好像是没什么关系。由于是考虑区间内数的个数,不妨设想有一个前缀和数组s,这样$[a_i, b_i]$至少有$c_i$个元素就可以表示成$s[b_i] - s[a_i-1] >= c[i]$,我们会得到若干个这样的不等式,就可以做差分约束了——然而值得注意的是,刚才的例子里是小于等于,而这里是大于等于。所以这里的解集应当取到最大,所以求的是最长路而不是最短路

  真的仅仅只是这样吗?我们忽略了题目给的一个条件——每个位置只能放一个数,所以我们的约束条件少了,要加上对于每一个位置i,$s[i]-s[i-1] \geq 0, s[i]-s[i-1] \leq 1$(其实$s[i]-s[i-1]$)就是i这个位置的数的个数,不是0就是1. 对于小于等于的情况,同时乘以-1转换成大于等于的形式,$s[i-1]-s[i] \geq -1$即可

code

  注意Dijkstra是不能做负权的(有$s[i-1]-s[i] \geq -1$的存在),所以用SPFA

/*By QiXingzhi*/
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define r read()
#define Max(a,b) (((a)>(b)) ? (a) : (b))
#define Min(a,b) (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int MAXN = ;
const int INF = ;
inline int read(){
int x = ; int w = ; register int c = getchar();
while(c ^ '-' && (c < '' || c > '')) c = getchar();
if(c == '-') w = -, c = getchar();
while(c >= '' && c <= '') x = (x << ) +(x << ) + c - '', c = getchar();
return x * w;
}
int N,L,R;
int a,b,c,d[MAXN],vis[MAXN];
int first[MAXN*],nxt[MAXN*],to[MAXN*],cost[MAXN*],num_edge;
queue <int> q;
inline void add(int u, int v, int w){
// printf("%d->%d (%d)\n", u,v,w);
to[++num_edge] = v;
cost[num_edge] = w;
nxt[num_edge] = first[u];
first[u] = num_edge;
}
inline void SPFA(int s){
for(int i = ; i <= N; ++i) d[i] = -INF;
d[s] = ;
q.push(s);
int u, v;
while(!q.empty()){
u = q.front();
q.pop();
vis[u] = ;
for(int i = first[u]; i; i = nxt[i]){
v = to[i];
if(d[u] + cost[i] > d[v]){
d[v] = d[u] + cost[i];
if(!vis[v]){
vis[v] = ;
q.push(v);
}
}
}
}
}
inline void Init(){
memset(vis,,sizeof(vis));
memset(first,,sizeof(first));
memset(nxt,,sizeof(nxt));
memset(to,,sizeof(to));
memset(cost,,sizeof(cost));
}
int main(){
// freopen(".in","r",stdin);
while(scanf("%d",&N) == ){
L = N+, R = -;
Init();
for(int i = ; i <= N; ++i){
a=r,b=r,c=r;
add(a, b+, c);
L = Min(L, a);
R = Max(R, b+);
}
for(int i = ; i <= R; ++i){
add(i+, i, -);
add(i, i+, );
}
SPFA(L);
// printf("R+1 = %d L+1 = %d\n",R+1,L+1);
printf("%d\n", d[R]);
}
return ;
}

☆ [POJ1021] Intervals 「差分约束」的更多相关文章

  1. poj1716 Integer Intervals(差分约束)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Integer Intervals Time Limit: 1000MS   Me ...

  2. POJ1201 Intervals (差分约束)

    You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn. Write a program that: ...

  3. poj 1716 Integer Intervals(差分约束)

    1716 -- Integer Intervals 跟之前个人赛的一道二分加差分约束差不多,也是求满足条件的最小值. 题意是,给出若干区间,需要找出最少的元素个数,使得每个区间至少包含两个这里的元素. ...

  4. poj 1201 Intervals(差分约束)

    做的第一道差分约束的题目,思考了一天,终于把差分约束弄懂了O(∩_∩)O哈哈~ 题意(略坑):三元组{ai,bi,ci},表示区间[ai,bi]上至少要有ci个数字相同,其实就是说,在区间[0,500 ...

  5. Intervals(差分约束)

    http://poj.org/problem?id=1201 题意:给出N个整数区间[ai,bi],并且给出一个约束ci,( 1<= ci <= bi-ai+1),使得数组Z在区间[ai, ...

  6. POJ 1201 Intervals (经典) (差分约束)

    <题目链接> 题目大意:给你$n$段区间,$a_i,b_i,c_i$ 表示在 $[a_i,b_i]$ 区间内至少要选择$c_i$个点.现在问你在满足这n个条件的情况下,最少要选多少个点? ...

  7. HDU 1384 Intervals【差分约束-SPFA】

    类型:给出一些形如a−b<=k的不等式(或a−b>=k或a−b<k或a−b>k等),问是否有解[是否有负环]或求差的极值[最短/长路径].例子:b−a<=k1,c−b&l ...

  8. 【题解】 POJ 1201 Intervals(差分约束)

    懒得复制,戳我戳我 Solution: 这道题就是一个板子题 抽象成第\(a\)至第\(b\)间选择数的个数为\(c\),我们就可以用前缀和来表示,这样就可以得到不等式\(s[b]-s[a-1]> ...

  9. POJ1201 Intervals 【差分约束】

    题目链接 POJ1201 题解 差分约束 令\(a[i]\)表示是否选择\(i\),\(s[i]\)表示\(a[i]\)的前缀和 对\(s[i] \quad i \in [-1,50000]\)分别建 ...

随机推荐

  1. 008-我的博友不锈钢钥匙扣上的随身金属外壳可启动U盘-20190413

      008-我的博友不锈钢钥匙扣上的随身金属外壳可启动U盘-20190413

  2. Really Big Numbers CodeForces - 817C (数学规律+二分)

    C. Really Big Numbers time limit per test 1 second memory limit per test 256 megabytes input standar ...

  3. 使用VBA进行JS加密的反混淆,还原JS代码。

    本文地址:http://www.cnblogs.com/Charltsing/p/JSEval.html 联系QQ:564955427 类似下面的代码是登陆 全国企业信用信息公示系统(安徽)(网址:h ...

  4. asp.net core下一个简单的分页技术

    在做web应用的时候免不了要对数据进行分页,我最近在做asp.net core的开发的时候就遇到了这个需求,现在简单的记录一下: public class PaginatedList<T> ...

  5. PHP中对象的深拷贝与浅拷贝

    先说一下深拷贝和浅拷贝通俗理解 深拷贝:赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个 浅拷贝:赋值时,引用赋值,相当于取了一个别名.对其中一个修改,会影响另一个 PHP中, = ...

  6. mysql异常:Packet for query is too large (10240 > 1024). You can change this value

    出现这个问题的原因是:mysql的配置文件中 max_allowed_packet 设置过小,mysql根据配置文件会限制server接受的数据包大小. 还有人会说我操作的数据量明显没有超过这个值为啥 ...

  7. [转帖]Linux命令中特殊符号

    Linux命令中特殊符号 转自:http://blog.chinaunix.net/uid-16946891-id-5088144.html   在shell中常用的特殊符号罗列如下:# ; ;; . ...

  8. 设置SQLServer数据库内存

    需要设置SQLServer数据库的内存配置.登录数据库,这里使用的是SQLServer2008,右键点击最上方的服务器名,在弹出的菜单中,点击属性] 打开服务器属性窗口.默认显示的是第一项[常规]内容 ...

  9. mac下php开发环境的搭建

    1.phpstorm 在官网:https://www.jetbrains.com/phpstorm/,下载最新版:phpstorm-2016.2.1 在http://15.idea.lanyus.co ...

  10. 剑指offer(11)

    题目: 输入一个链表,输出该链表中倒数第k个结点. 思路: 我们一先想到的应该是循环两次链表,第一次获得它的长度,然后用长度-k,得出目标节点在链表的第几位,再循环一次. 如果要求只用一次循环的话,我 ...