题解 | #[NOIP2012]借教室#

[NOIP2012]借教室

https://ac.nowcoder.com/acm/contest/19684/A

A 借教室

法一:线段树 区间修改 / 懒标记

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 1e6+10;

int n,m;
int w[N];
struct node{
    int l,r;
    ll lazy;
    ll minm;
}tr[N*4];

void pushdown(int u){
    auto &rt=tr[u],&le=tr[u<<1],&ri=tr[u<<1|1];
    if(rt.lazy){
        le.lazy+=rt.lazy;
        ri.lazy+=rt.lazy;
        le.minm+=rt.lazy;
        ri.minm+=rt.lazy;
        rt.lazy=0;
    }
}

void pushup(int u){
    tr[u].minm=min(tr[u<<1].minm,tr[u<<1|1].minm);
}

void build(int u,int l,int r){
    tr[u]={l,r,0,10000000000};
    
    if(l==r) {
        tr[u].minm=w[l];
        return ;
    }
    
    int mid=l+r>>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
    pushup(u);
}

void modify(int u,int l,int r,int v){
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].lazy+=v;
        tr[u].minm+=v;
    }
    else{
        pushdown(u);
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid) modify(u<<1,l,r,v);
        if(r>mid)  modify(u<<1|1,l,r,v);
        pushup(u);
    }
}

ll query(int u,int l,int r){
     if(tr[u].l>=l&&tr[u].r<=r) return tr[u].minm;
    
     int mid=tr[u].l+tr[u].r>>1;
     ll minm=1e10;
     
     if(l<=mid) minm=query(u<<1,l,r);
     if(r>mid)  minm=min(minm,query(u<<1|1,l,r));
    
    return minm;
}

int main(){
    scanf("%d%d",&n,&m);
    
    for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    
    build(1,1,n);
    
    int f=0;
    for(int i=1;i<=m;i++){
        int d,s,t; scanf("%d%d%d",&d,&s,&t);
        modify(1,s,t,-d);
        if(query(1,s,t)<0) {  f=i;  break; }
    }
    
    if(f) {
        puts("-1");
        printf("%d\n",f);
    } 
    else puts("0");
    
    return 0;
}

法二:二分 + 差分

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 1e6+10;

int n, m;
int r[N],c[N];
struct node{
    int d,s,t;
}p[N];

bool check(int x){
    memset(c,0,sizeof c);
    
    for(int i=1;i<=x;i++){
        int d=p[i].d,s=p[i].s,t=p[i].t;
        c[s]+=d,c[t+1]-=d;
    }
    
    for(int i=1;i<=n;i++) {
        c[i]+=c[i-1];
        if(c[i]>r[i]) return true;
    }
    
    return false;
}

int main(){
    scanf("%d%d",&n,&m);
    
    for(int i=1;i<=n;i++) scanf("%d",&r[i]);
    
    for(int i=1;i<=m;i++) {
        int d,s,t; scanf("%d%d%d",&d,&s,&t);
        p[i]={d,s,t};
    }
    
    int l=1,r=m,f=0;
    while(l<r){
        int mid=l+r>>1;
        if(check(mid))  f=r=mid;  // 不合法
        else l=mid+1;
    }
    
    if(f)  {
        puts("-1");
        printf("%d\n",f);
    }
    else  puts("0");
    
    return 0;
}


全部评论

相关推荐

点赞 评论 收藏
转发
1 收藏 评论
分享
牛客网
牛客企业服务