牛客练习赛56 D.小翔和泰拉瑞亚(线段树)

传送门

由于要求最小差值

考虑枚举每个序号 i n d e x index index作为最小值来求

首先 i n d e x index index的值越小越好,所以我们把所有覆盖 i n d e x index index的区间加进去

但是这样有些位置的数字也减小了啊!!但其实差值是不变的,所以一定是更优的

于是我们可以把所有区间按照左端点排序

只要左端点比 i n d e x index index小就说明覆盖了 i n d e x index index(因为 i n d e x index index 1 1 1起)

我们就加进来放在线段树上,然后查询区间最大值

然后之前加入的那些区间,我们在右端点处打个标记,说明它的作用到右端点位置

到了这个点,我们就消除那个区间的影响就好了

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (rt<<1|1)
#define lson ls,l,mid
#define rson rs,mid+1,r
const int maxn = 2e5+10;
int n,m,ans;
struct p
{
	int l,r,w;
	bool operator < (const p&tmp )	const
	{
		if( l==tmp.l )	return r<tmp.r;
		return l<tmp.l;
	}
}a[maxn];
vector<p>vec[maxn];
int w[maxn<<2],laz[maxn<<2],h[maxn];
void pushdown(int rt,int l,int r)
{
	if( laz[rt]==0 )	return;
	laz[ls] += laz[rt],laz[rs] +=laz[rt];
	w[ls] +=laz[rt], w[rs] += laz[rt];
	laz[rt] = 0;
}
void build(int rt,int l,int r)
{
	if( l==r )	{ w[rt] = h[l]; return; }
	build(lson); build(rson);
	w[rt] = max( w[ls],w[rs] );
}
void add(int rt,int l,int r,int L,int R,int val)
{
	if( l>=L&&r<=R )	{ laz[rt]+=val; w[rt]+=val; return; }
	if( l>R||r<L )	return;
	pushdown(rt,l,r);
	add(lson,L,R,val); add(rson,L,R,val);
	w[rt] = max( w[ls],w[rs] );
}
int ask(int rt,int l,int r,int index)
{
	if( l>index||r<index )	return 0;
	if( l==r&&l==index )	return w[rt];
	pushdown(rt,l,r);
	return ask(lson,index)+ask(rson,index);
}
signed main()
{
	cin >> n >> m;
	for(int i=1;i<=n;i++)	cin >> h[i];
	build(1,1,n);
	for(int i=1;i<=m;i++)
		cin >> a[i].l >> a[i].r >> a[i].w;
	sort( a+1,a+1+m );
	int last = 1,ans = 0;
	for(int i=1;i<=n;i++)
	{
		while( a[last].l<=i&&last<=m )
		{
			add( 1,1,n,a[last].l,a[last].r,-a[last].w );
			vec[a[last].r].push_back( a[last] );
			last++;
		}
		ans = max( ans,w[1]-ask(1,1,n,i) );
		for(int j=0;j<vec[i].size();j++)
			add(1,1,n,vec[i][j].l,vec[i][j].r,vec[i][j].w);
	}
	cout << ans;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值