解题思路
正解好像是什么前缀和+二分,没想到。。就写了个线段树骗分,结果擦着边过了??线段树中维护一个区间和 and 最小值即可。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN = 1e6+5;
typedef long long LL;
int n,m,a[MAXN],d[MAXN],s[MAXN],t[MAXN];
LL sum[MAXN<<1];
int lazy[MAXN<<1],mn[MAXN<<1],ans;
bool flag;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
inline int min(int x,int y){
return x>y?y:x;
}
inline void build(int x,int l,int r){
if(l==r){
sum[x]=a[l];
mn[x]=a[l];
return ;
}
int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
sum[x]=sum[x<<1]+sum[x<<1|1];
mn[x]=min(mn[x<<1],mn[x<<1|1]);
}
inline void pushdown(int x,int ln,int rn){
lazy[x<<1]+=lazy[x];
sum[x<<1]+=(LL)ln*lazy[x];
lazy[x<<1|1]+=lazy[x];
sum[x<<1|1]+=(LL)rn*lazy[x];
mn[x<<1]+=lazy[x];mn[x<<1|1]+=lazy[x];
lazy[x]=0;
}
inline void update(int x,int l,int r,int L,int R,int k){
if(L<=l && r<=R) {
sum[x]-=k*(r-l+1);
mn[x]-=k;lazy[x]-=k;
if(mn[x]<0) flag=1;
return ;
}
int mid=l+r>>1;
if(lazy[x]) pushdown(x,mid-l+1,r-mid);
if(mid>=L) update(x<<1,l,mid,L,R,k);
if(mid<R) update(x<<1|1,mid+1,r,L,R,k);
sum[x]=sum[x<<1]+sum[x<<1|1];
mn[x]=min(mn[x<<1],mn[x<<1|1]);
}
int main(){
n=rd(); m=rd();
for(register int i=1;i<=n;i++) a[i]=rd();
build(1,1,n);
for(register int i=1;i<=m;i++){
d[i]=rd(),s[i]=rd(),t[i]=rd();
if(!flag) {
update(1,1,n,s[i],t[i],d[i]);
if(flag==1) ans=i;
}
}
if(!flag) cout<<0<<endl;
else{
puts("-1");
printf("%d",ans);
}
return 0;
}
二分+前缀和
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+6;
int s[MAXN],t[MAXN],b[MAXN],a[MAXN],d[MAXN],sum[MAXN];
int n,m,ans;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
inline bool check(int x){
memset(d,0,sizeof(d));
for(register int i=1;i<=x;i++){
d[s[i]]+=b[i];
d[t[i]+1]-=b[i];
}
for(register int i=1;i<=n;i++){
sum[i]=sum[i-1]+d[i];
if(sum[i]>a[i]) return false;
}
return true;
}
int main(){
n=rd();m=rd();
for(register int i=1;i<=n;i++) a[i]=rd();
for(register int i=1;i<=m;i++) b[i]=rd(),s[i]=rd(),t[i]=rd();
int l=1,r=m;
while(l<=r) {
int mid=l+r>>1;
if(check(mid)) {
ans=mid;
l=mid+1;
}else r=mid-1;
}
if(check(m)) cout<<0<<endl;
else{
cout<<-1<<endl;
printf("%d",ans+1);
}
return 0;
}