【区间问题】 hiho一下第152周 - 区间求差

博客详细解释了如何处理区间问题,特别是针对hiho第152周的区间求差挑战。通过将区间左端点标记为绿色,右端点标记为蓝色,按顺序排序并使用计数变量追踪区间数量,可以解决多种问题,如求区间并集长度和找出最多被覆盖的线段。在本题中,计算A - B的长度涉及对A和B集合的端点进行标记和计数,找到满足特定条件的线段。

题目链接:

hiho一下第152周 - 区间求差

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

给定两个区间集合 A 和 B,其中集合 A 包含 N 个区间[ A1A2 ], [ A3A4 ], ..., [ A2N-1A2N ],集合 B 包含 M 个区间[ B1B2 ], [ B3B4 ], ..., [ B2M-1B2M ]。求 A - B 的长度。

例如对于 A = {[2, 5], [4, 10], [14, 18]}, B = {[1, 3], [8, 15]}, A - B = {(3, 8), (15, 18]},长度为8。

输入

第一行:包含两个整数 N 和 M (1 ≤ NM ≤ 100000)。

第二行:包含 2N 个整数 A1A2, ..., A2N (1 ≤ Ai ≤ 100000000)。

第三行:包含 2M 个整数 B1B2, ..., B2M (1 ≤= Bi ≤ 100000000)。

输出

一个整数,代表 A - B 的长度。

样例输入
3 2
2 5 4 10 14 18
1 3 8 15
样例输出
8
思路分析:


一般区间问题:

对于由2N个点所构成的N个区间,用绿色表示区间左端点,蓝色表示右端点。将所有的点放入容器中并按升序排序,设置计数变量cnt标记当前位置由几个区间所包含,然后从小到大依次遍历2N个点,如果是左端点则cnt++,右端点则cnt--。计算出每一段所属区间的个数(cnt)就可以做很多事情,比如要求多个区间并集的长度,只要求出所有cnt大于0的线段的长度和即可。另外,还可以求出被覆盖最多次的线段(cnt的最大值)等等。值得注意的是,对于重合的点的处理可能需要仔细考虑,而本题中无需考虑,可将重合的点看成多个重叠的长度为0的线段,并不影响我们的计算结果。


回到本题,要计算A - B的长度,就要先考虑好哪些点是属于A - B这个集合的,存在什么样的特征。我们可以将A, B集合中的左右端点分别用四种标记来标识,放到容器中然后从小到大排序。设置变量cnta与cntb分别对集合A与集合B进行计数,即当前点为集合A的左端点时cnta++,为集合A右端点时,cnta--。集合b中的点同理。显然,A - B等价于所有满足cnta > 0且cntb=0的线段。


参考代码如下:

/***********************
[Hihocoder] 第152周 - 区间求差
Author:ZhengJianlong
Time:2017/6/01 15:04
language:C++
http://blog.youkuaiyun.com/z8596300
***********************/
#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int a[200005]={0}, b[200005]={0};

bool Compare(pair<int, int> p1, pair<int, int> p2)
{
	if(p1.second != p2.second)
		return p1.second < p2.second;
	else
		return p1.first <p2.first;
}
int main()
{
	int N, M;
	vector <pair <int, int>> pset;

//	freopen("in.txt", "r", stdin);

	cin>>N>>M;
	for(int i=0; i<2*N; i++)
		cin>>a[i];
	for(int i=0; i<2*M; i++)
		cin>>b[i];

	for(int i=0; i<2*N; i++)
	{
		if(i%2 == 0)
			pset.push_back(make_pair(0, a[i]));
		else
			pset.push_back(make_pair(1, a[i]));
	}

	for(int i=0; i<2*M; i++)
	{
		if(i%2 == 0)
			pset.push_back(make_pair(2, b[i]));
		else
			pset.push_back(make_pair(3, b[i]));
	}

	sort(pset.begin(), pset.end(), Compare);


	int cnta=0, cntb=0, ans=0;
	for(int i=0; i<pset.size()-1; i++)
	{
		pair<int, int> cpair = pset[i];
		switch(cpair.first)
		{
			case 0:
				cnta++;
				break;
			case 1:
				cnta--;
				break;
			case  2:
				cntb++;
				break;
			case 3:
				cntb--;
				break;
			default:
				break;
		}

		if(cnta>0 && cntb==0)
			ans += (pset[i+1].second - pset[i].second);
	}

	cout<<ans;
	return 0;
}


内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值