最小值线段树模板题。
按顺序更新区间,维护最小值。最小值小于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;
}