League of Legends -- 2021牛客暑期多校训练营2

该博客探讨了一道计算机科学竞赛题,涉及线段的分组问题,要求每组线段都有交集。博主首先介绍了如何处理复杂线段关系,然后详细解释了动态规划(DP)的转移方程,并提出了使用单调队列进行优化的方法。通过排序和剔除完全包含的线段,博主展示了如何减少计算复杂性并提高算法效率。最终,给出了完整的C++代码实现。
摘要由CSDN通过智能技术生成

题意:把给出的n条线段分成k组,使得每组都保证线段有交,或者是一条线。求最后所有k个组交的长度的和。

想做这道题首先要搞清楚几个点:
1,怎么处理复杂关系的区间。
2,知道是dp之后,怎么推转移方程。
3,如何进行优化。

这里面最难想的可能是第一个点了。因为在做这道题前我已经假定这道题是dp题,于是我首先试着写一下转移方程

for(int i = 1;i <= 0;i++)       //n person
	for(int j = 1;j <= k j++)        //k group
		for(int l = 1;l < i;l++)         //from l to i
			dp[i][j] = trans{
   dp[l][j-1] + val}

朴素dp的大体形式就是这样,由于dp之间的转移是根据区间相差1的转移,所以根据题目规定区间内必有交可以确定,vala[l].r-a[i].l,即 l 与 i之间可以获得的贡献值。
要进行这样的转移,那原始的数据必定不满足,所以我们处理一下原数据。
即根据以下顺序对线段进行排序。(从别人那新学的排序写法)

sort(a + 1, a + 1 + n, [&](node k1, node k2) {
   
        if (k1.r == k2.r) return k1.l > k2.l;          //右区间相同,区间逐渐变大
        return k1.r < k2.r;
    });

排完序可以得到在这里插入图片描述
我们可以发现一些能完全包含出现过的线段的,根本没必要放在同一个集合里,放了也可以但是没有贡献。这为我们提供了方便。最后计算答案时,我们不用管这些大集合,因为他们可以任意的放入有完全包含关系的集合,也可以另开集合做为贡献。所以我们剃掉这些包含其他线的大集合,放入一个容器。

接下来我们获得了所有的小线段,开始进行dp,朴素dp肯定会tle,我们发现线段之间会不会出现没有交集的情况我们恰好可以用单调队列模拟,若没有交集则弹出头部,直到再次出现交集,我们在那个点转移。然后就是经典的单调队列优化,每次转移完,把尾部更新。

dp[i][l] = dp[q[head]][l - 1] + seg
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值