[Luogu] P1083 [NOIP2012 提高组] 借教室(线段树)

题目链接

最小值线段树模板题。
按顺序更新区间,维护最小值。最小值小于0的时候就找到矛盾了。复杂度 O ( m l o g n ) O(mlogn) O(mlogn)

完整代码:

#include<bits/stdc++.h>
#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define INF 0x3f3f3f3f
typedef long long ll;
const int maxn = 1e6+5;

using namespace std;

int n,m;
ll a[maxn];
struct seg_tree
{
	int l,r;
	ll minn,lazy;
}tree[maxn<<2];

void pushup(int rt)
{
	tree[rt].minn=min(tree[rt<<1].minn,tree[rt<<1|1].minn);
}

void build(int l, int r, int rt)
{
	tree[rt].l=l, tree[rt].r=r;
	if (l==r)
	{
		tree[rt].minn=a[l];
		return;
	}
	int mid=(l+r)/2;
	build(l,mid,rt<<1);
	build(mid+1,r,rt<<1|1);
	pushup(rt);
}

void pushdown(int rt)
{
	if (tree[rt].lazy!=0)
	{
		tree[rt<<1].lazy+=tree[rt].lazy;
		tree[rt<<1|1].lazy+=tree[rt].lazy;
		tree[rt<<1].minn+=tree[rt].lazy;
		tree[rt<<1|1].minn+=tree[rt].lazy;
		tree[rt].lazy=0;
	}
}

void add(int L, int R, ll val, int l, int r, int rt)
{
	if (L<=l && R>=r)
	{
		tree[rt].minn+=val;
		tree[rt].lazy+=val;
		return;
	}
	int mid=(l+r)/2;
	pushdown(rt);
	if (L<=mid) add(L,R,val,l,mid,rt<<1);
	if (R>mid) add(L,R,val,mid+1,r,rt<<1|1);
	pushup(rt);
}

ll query(int L, int R, int l, int r, int rt)
{
	if (L<=l && R>=r)
	{
		return tree[rt].minn;
	}
	pushdown(rt);
	int mid=(l+r)/2;
	ll ans=INF;
	if (L<=mid) ans=min(ans,query(L,R,l,mid,rt<<1));
	if (R>mid) ans=min(ans,query(L,R,mid+1,r,rt<<1|1));
	return ans;
}

int main()
{
   	FAST; 
   	int flag=1;
	cin>>n>>m;
	for (int i=1; i<=n; i++) cin>>a[i];	
	build(1,n,1);
	for (int i=1; i<=m; i++)
	{
		int x,l,r,ans=INF;
		cin>>x>>l>>r;
		add(l,r,-x,1,n,1);
		ans=query(l,r,1,n,1);
		if (ans<0)
		{
			flag=0;
			cout<<-1<<endl;
			cout<<i<<endl;
			break;
		}
	}
	if (flag==1) cout<<0<<endl;

return 0;
}


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值