1509 Intervals

本文解析了如何将差分约束问题转化为图论中的最短路径问题,并通过实例展示了如何使用C++实现SPFA算法求解满足条件的s数组。重点在于理解不等式转换和邻接矩阵构建的过程。

1509 Intervals

很明显这是一个差分约束的题目
求满足多个不等式的条件的东西,可以把不等式转换成图论中最短路问题然后进行松弛
这是一个很标准的差分约束系统问题
要求的不等式条件是:s[b[i]]-s[a[i]-1]≥c[i],其中s数组表示当前位置为止选择的个数
然后转换一下
s[b[i]] ≥ s[a[i]-1]+c[i]
s[i] ≥ s[i-1]+0
s[i-1] ≥ s[i]+(-1)

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=5e4+10;
const int INF=0x3fffffff;
typedef long long LL;
//差分约束系统标准题
int head[maxn],dis[maxn],vis[maxn];
struct node
{
    int to,dis,next;
}ed[maxn*2];
int cnt,n;
void add(int x,int y,int z)//邻接表建图
{
    ed[++cnt].dis=z;
    ed[cnt].to=y;
    ed[cnt].next=head[x];
    head[x]=cnt;
}
queue<int> q;
void spfa(int st)
{
    for(int i=1;i<=n;i++) dis[i]=-INF;
    //因为是求最长路
    dis[st]=0;
    q.push(st);
    vis[st]=1;
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        vis[t]=0;
        for(int i=head[t];i;i=ed[i].next)
        {
            int op=ed[i].to;
            if(dis[op]<dis[t]+ed[i].dis)//建立最长路
            {  
                dis[op]=dis[t]+ed[i].dis;
                if(!vis[op])
                {
                    vis[op]=1;
                    q.push(op);
                }
            }
        }
    }
}
int main(){
    scanf("%d",&n);
    int x,y,z;
    int st=INF,ed=-INF;
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d %d",&x,&y,&z);
        add(x-1,y,z);  //建边
        st=min(st,x-1);  //记得减一
        ed=max(ed,y);
    }
    for(int i=st;i<=ed;i++)
    {
        add(i-1,i,0);//差分建边,这个建边是根据不等式进行建边
        add(i,i-1,-1);
    }
    spfa(st);
    printf("%d\n",dis[ed]);
return 0;
}
在C++中处理区间(Intervals)通常涉及对区间数据结构的操作,例如区间的表示、合并、排序、查找交集或执行数值方法中的区间划分。以下是一些常见的与区间相关的处理方法及其代码示例。 ### 区间表示 区间可以用一个简单的结构体或类来表示: ```cpp struct Interval { double start; double end; Interval(double s, double e) : start(s), end(e) {} }; ``` ### 区间排序 可以通过重载 `<` 运算符来对区间进行排序,例如按照起始点排序: ```cpp bool operator<(const Interval& a, const Interval& b) { return a.start < b.start; } // 示例使用 std::vector<Interval> intervals = {{1.0, 3.0}, {2.0, 4.0}, {0.5, 2.5}}; std::sort(intervals.begin(), intervals.end()); ``` ### 合并重叠区间 合并重叠区间是常见的任务,例如在事件调度或图形学中。算法步骤包括排序区间并遍历它们以合并重叠部分: ```cpp std::vector<Interval> mergeIntervals(const std::vector<Interval>& intervals) { if (intervals.empty()) return {}; std::vector<Interval> sortedIntervals = intervals; std::sort(sortedIntervals.begin(), sortedIntervals.end()); std::vector<Interval> merged; merged.push_back(sortedIntervals[0]); for (size_t i = 1; i < sortedIntervals.size(); ++i) { Interval& last = merged.back(); const Interval& current = sortedIntervals[i]; if (current.start <= last.end) { // 合并区间 last.end = std::max(last.end, current.end); } else { merged.push_back(current); } } return merged; } ``` ### 区间二分法(Bisection Method) 对于求解函数根的问题,可以使用区间二分法[^2]。以下是一个实现示例: ```cpp double bisectionMethod(double (*f)(double), double a, double b, double tolerance) { if (f(a) * f(b) >= 0) { // 区间内没有根或者无法保证存在根 throw std::invalid_argument("Function must have opposite signs at endpoints."); } while ((b - a) / 2.0 > tolerance) { double midpoint = (a + b) / 2.0; if (f(midpoint) == 0) { return midpoint; } if (f(a) * f(midpoint) < 0) { b = midpoint; } else { a = midpoint; } } return (a + b) / 2.0; } ``` ### 区间交集检测 检测两个区间是否有交集,并计算交集: ```cpp bool hasIntersection(const Interval& a, const Interval& b) { return !(a.end < b.start || b.end < a.start); } Interval getIntersection(const Interval& a, const Interval& b) { if (!hasIntersection(a, b)) { throw std::invalid_argument("Intervals do not intersect."); } return Interval(std::max(a.start, b.start), std::min(a.end, b.end)); } ``` 这些代码片段涵盖了区间的基本操作和常见用例。通过结合具体需求,如数值分析、几何问题或游戏逻辑中的区间处理,可以进一步扩展这些功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值