蓝桥杯day6——离散化与合并区间
离散化
- 我自己的定义:一个超大数组,需要对数组中有限的位置进行操作,而离散化是将这有限的位置挨个存进一个数组a,并进行排序和去重,然后将需要的操作映射到一个数组b上,顺序和数组a一致。
- 作用:面对一个无限的序列时的有限操作,有效的压缩了空间
例题
假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。
现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。
接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。
输入格式
第一行包含两个整数 n 和 m。
接下来 n 行,每行包含两个整数 x 和 c。
再接下来 m 行,每行包含两个整数 l 和 r。
输出格式
共 m 行,每行输出一个询问中所求的区间内数字和。
数据范围
−109≤x≤109,
1≤n,m≤105,
−109≤l≤r≤109,
−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
N = 300010
n, m = map(int, input().split())
a, s = [0] * N, [0] * N
alls = []
add, query = [], []
def find(x) :
global alls
l, r= 0, len(alls) - 1
while l < r :
mid = l + r >> 1
if alls[mid] >= x : r = mid
else : l = mid + 1
return r + 1
for i in range(n) :
x, c = map(int, input().split())
add.append([x, c])
alls.append(x)
for i in range(m) :
l, r = map(int, input().split())
alls.append(l)
alls.append(r)
query.append([l, r])
alls = list(set(alls))
alls.sort()
for i in add :
x = find(i[0])
a[x] += i[1]
for i in range(1, len(alls) + 1) :
s[i] = s[i - 1] + a[i]
for i in query :
l = find(i[0])
r = find(i[1])
print(s[r] - s[l - 1])
注意的点
因为用到了前缀和,求前缀和时预留0索引,所以在二分查找时返回r + 1
合并区间
这题是我的老熟人了,在刷代码随想录的时候就遇到了,贪心!贪心!贪心!
这题由于只让求个数所以处理逻辑相对简单一点
- 贪心策略:局部最优解:第i个区间在碰到的外层比i + 1个区间内层大时,更新当前维护的区间的最外层:即i和i + 1区间最外层的最大值,否则则将结果 + 1(这里我是将原来区间个数一个个减去的)
例题
给定 n 个区间 [li,ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如:[1,3] 和 [2,6] 可以合并为一个区间 [1,6]。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含两个整数 l 和 r。
输出格式
共一行,包含一个整数,表示合并区间完成后的区间个数。
数据范围
1≤n≤100000,
−109≤li≤ri≤109
输入样例:
5
1 2
2 4
5 6
7 8
7 9
输出样例:
3
代码如下:
import functools
n = int(input())
a = []
for i in range(n) :
a.append(list(map(int, input().split())))
def cmp(x, y) :
if x[0] > y[0] :
return 1
elif x[0] == y[0] :
if x[1] > y[1] :
return 1
else :
return -1
else :
return -1
a.sort(key=functools.cmp_to_key(cmp))
res = int(n)
i = 0
while i < n - 1 :
while i < n- 1 and a[i][1] >= a[i + 1][0]:
res -= 1
a[i + 1][1] = max(a[i][1], a[i + 1][1])
i += 1
i += 1
print(res)
一些小细节
这里面我学到了Python排序技巧:
自定义排序,需要给key赋值,可以用lambda表达式,也可以用functools的cmp_to_key()方法自定义一个cmp函数
cmp函数定义值得注意的是当返回正数时,位置交换,负数时位置不交换
要模拟C中for (int i = 0; i < n ; i++) {i++}
:即在for循环体内改变遍历的位置
Python可以用while模拟
i = 0
while i <= n :
i += 1
总结
就此将算法基础部分学完了,明天开启图论,前进!前进!前进!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!