LUOGU P1083 借教室

传送门

解题思路

正解好像是什么前缀和+二分,没想到。。就写了个线段树骗分,结果擦着边过了??线段树中维护一个区间和 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;
}
posted @ 2018-08-03 09:18  Monster_Qi  阅读(118)  评论(0编辑  收藏  举报