【差分约束系统】间隔Intervals
并没有什么用的更新时间
【2019/07/10】 题目及代码(伪)、题解更新
【2021/05/16】 我人真的傻了 这已经超出碳基生物的整活范围了 没想到时隔多年重学差分约束系统 搜到的题解竟然是两年前自己打的555我真的是越学越菜 不过代码好像贴成楼下树形DP的了 更新了代码
间隔Intervals
tip:翻译来自谷歌,如有出入请见谅
- 题目描述
给定n个闭合的整数区间[ai,bi]和n个整数c1,…,cn。
编写一个程序: 从标准输入读取间隔数,它们的终点和整数c1,…,cn, 计算整数集合Z的最小尺寸,它至少具有ci公共元素的间隔[ai, bi],对于每个i = 1,2,…,n, 将答案写入标准输出。
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. - 输入输出格式
- 输入格式:
输入的第一行包含整数n(1 <= n <= 50000) - 间隔数。以下n行描述了间隔。输入的第(i + 1)行包含由单个空格分隔的三个整数ai,bi和ci,并且使得0 <= ai <= bi <= 50000并且1 <= ci <= bi-ai + 1。
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. - 输出格式:
对于每个i = 1,2,…,n,输出恰好包含一个等于集合Z的最小尺寸的整数,该集合Z至少与区间[ai,bi]共享ci元素。
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. - 输入输出样例
- 输入样例#1:
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1 - 输出样例#1:
6 - 题解
题目难度:★★★☆☆
思路:假设d[i] 是 [1,i] 至少有多少个点被选中, 特殊地, d[0] = 0。 每个区间的描述可以转化为d[R] - d[L-1] >= w。(因为d[L]也要选中, 左闭右闭区间, 所以要减d[L-1])
因为d[i]描述了一个求和函数,所以对于d[i]和d[i-1]其实是有自身限制的,考虑到每个点有选和不选两种状态,所以d[i]和d[i-1]需要满足以下不等式: 0 <= d[i] - d[i-1] <= 1 (即第i个数选还是不选)
这样, 我们就有了3个约束不等式
d[R] - d[L-1] >= w (1)
d[i] - d[i-1] >= 0 (2)
d[i-1] - d[i] >= -1 (3)
求出d[min]到d[max]的最长路, d[max] 就是这个区间最少要放多少个球。
差分约束系统
对于每个不等式 x[i] - x[j] >= a[k],对结点 j 和 i 建立一条 j -> i的有向边,边权为a[k],求x[n] - x[1] 的最大值就是求 1 到n的最长路。
假设d[i] 是 [1,i] 至少有多少个点被选中, 特殊地, d[0] = 0;
每个区间的描述可以转化为d[R] - d[L-1] >= w
因为d[i]描述了一个求和函数,所以对于d[i]和d[i-1]其实是有自身限制的,考虑到每个点有选和不选两种状态,
所以d[i]和d[i-1]需要满足以下不等式: 0 <= d[i] - d[i-1] <= 1 (即第i个数选还是不选) - 代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=50005;
struct edge
{
int v,w,next;
}e[maxn*3];
int head[maxn],dis[maxn],vis[maxn],cnt,n,u,v,w,st,fi;
void addedge(int u,int v,int w){
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt;
}
void spfa(int s){
queue<int> q;
for (int i=st;i<=fi+1;++i){
dis[i]=-INF;
vis[i]=0;
}
dis[s]=0,vis[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=0;
for (int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(dis[v]<dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
cout<<dis[fi+1]<<endl;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i){
scanf("%d%d%d",&u,&v,&w);
addedge(u,v+1,w);
fi=max(fi,v);
st=min(st,u);
}
for (int i=st;i<=fi+1;++i){
addedge(i,i+1,0);
addedge(i+1,i,-1);
}
spfa(st);
}
- 相关连接