CF1884C Medium Design 详解 线段树算贡献

原题链接:CF1884C Medium Design

一道不错的用线段树考虑贡献的题。

这里提供一种和官方题解思路不太一样的方法。

简要题意

给定 n n n 个区间,和一个长度为 m m m 且初始值全部为 0 0 0 的序列,任选其中的一些区间,在序列中进行区间加 1 1 1 操作,要使操作后序列的最大值与最小值之差最大,求出这个最大的差值。

思路

如果操作后最大值和最小值的位置确定,考虑每个区间,发现只有仅覆盖了最大值的区间会对答案产生贡献,其他区间(即覆盖了最小值的区间)则不用考虑,故可以反过来枚举所有最小值可能在的位置,对于每一个最小值的位置,可能的答案就是所有未覆盖该位置的区间进行区间加 1 1 1 后得到的序列里的最大值(即把最小值当成 0 0 0 考虑,每次区间加如果加到了最小值上一定不会使答案变大,故直接不考虑覆盖了最小值的区间),最后答案就是所有最大值里取最大。

显然这是个 RMQ 问题,用线段树维护。但每次枚举最小值直接暴力区间修改不覆盖最小值的区间复杂度无法接受,所以可以换一下思路,先把所有区间都覆盖一遍,然后从左到右枚举最小值的时候考虑每个区间的贡献:枚举到点 i i i 时,对于所有左端点在 i i i 的区间进行区间减 1 1 1,即这些区间会覆盖 i i i 及后面的一些位置,对于这些位置需要消除掉覆盖它们的区间的影响;同理,对于所有右端点在 i i i 的区间进行区间加 1 1 1加入这些区间对后面位置的影响(注意实现时加入影响的操作要在得到该位置的答案之后,因为该位置还在这些区间内,不能被这些区间贡献)。实现时只需要把区间分别挂到其左右端点上,用两个 vector 数组存即可(详见代码)。

还需要注意的一点,由于区间范围很大,需要离散化,离散化之后会使原本不相邻的两个区间变成相邻的,这会漏掉一些情况,当然可以人为在离散化对不相邻的区间之间增加一个位置,但实现起来稍微有点麻烦,而可以发现这道题如果存在不相邻的区间,就意味着序列的最小值一定是 0 0 0,答案就是对全部区间进行区间加以后的最大值,只需特判即可(注意序列最左边或最右边没被覆盖的情况需要单独考虑)。

Code

#include<bits/stdc++.h>
using namespace std;
const int N=500010;

struct Seg{
   int l,r;}seg[N];
bool cmp(Seg a,Seg b){
   return a.l==b.l?a
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值