借教室

题目链接

https://www.luogu.com.cn/problem/P1083

解题思路

第一种方法,也是我用的方法,因为另一种没想到。
线段树,维护区间最小值,比较简单,就是代码冗长
不会戳这里
第二种才是好方法,差分数组+二分
这道题就是我点差分数组才找到的,说来惭愧我并没用差分数组。
将二分请求出错是第几次,
check函数的话,从第一次请求到二分的这次请求循环,用差分数组记录,再循环1 ~ n求和,并比较与房间个数的大小关系,比房间多说明不可行,否则可行。

AC代码

//线段树 维护最小值 区间修改 区间查询
//提醒用scanf,printf否则可能超时
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
const int INF=0x3f3f3f3f;

int n,m,d,s,t,ans,j,rm[N];

struct TREE
{
    int l,r,lazy,m;    
}tr[N<<2];


void Build(int i,int l,int r)
{
    tr[i].l=l;
    tr[i].r=r;
    tr[i].lazy=0;
    tr[i].m=INF;
    if(l==r)
    {
        tr[i].m=rm[l];
        return ;
    }
    int mid=l+r>>1;
    Build(i<<1,l,mid);
    Build(i<<1|1,mid+1,r);
    tr[i].m=min(tr[i<<1].m,tr[i<<1|1].m);
    return ;
}

void PushDown(int i)
{
    if(tr[i].lazy==0) return ;
    tr[i<<1].lazy+=tr[i].lazy;
    tr[i<<1|1].lazy+=tr[i].lazy;
    tr[i<<1].m-=tr[i].lazy;
    tr[i<<1|1].m-=tr[i].lazy;
    tr[i].lazy=0;
}

void Update(int i,int l,int r,int sub)
{
    if(l<=tr[i].l && tr[i].r<=r)
    {
        tr[i].lazy+=sub;
        tr[i].m-=sub;
        return ;
    }
    PushDown(i);
    if(tr[i<<1].r>=l) Update(i<<1,l,r,sub);
    if(tr[i<<1|1].l<=r) Update(i<<1|1,l,r,sub);
    tr[i].m=min(tr[i<<1].m,tr[i<<1|1].m);
    return ;
}

int Query(int i,int l,int r)
{
    if(l<=tr[i].l && tr[i].r<=r) return tr[i].m;
    if(tr[i].r<l || tr[i].l>r) return INF;
    int res=INF;
    PushDown(i);
    if(tr[i<<1].r>=l) res=min(res,Query(i<<1,l,r));
    if(tr[i<<1|1].l<=r) res=min(res,Query(i<<1|1,l,r));
    tr[i].m=min(tr[i<<1].m,tr[i<<1|1].m);
    return res;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&rm[i]);
    Build(1,1,n);

    for(j=1;j<=m;j++)
    {
        scanf("%d%d%d",&d,&s,&t);
        if(d>Query(1,s,t))//d大于区间最小值 break 
        {
            ans=j;
            break;
        }
        Update(1,s,t,d); //维护区间最小值 
    } 
    if(j>m) puts("0");
    else puts("-1"),printf("%d\n",ans);
    return 0;
}

//差分数组+二分
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;

int diff[N],rm[N],d[N],l[N],r[N],sum[N];
int n,m;

bool check(int x)
{
    memset(diff,0,sizeof diff);//!
    for(int i=1;i<=x;i++)
    {
        diff[l[i]]+=d[i];
        diff[r[i]+1]-=d[i];
    }
    for(int i=1;i<=n;i++)
    {
        sum[i]=sum[i-1]+diff[i];
        if(sum[i]>rm[i]) return 0;
    }
    return 1;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&rm[i]);
    for(int i=1;i<=m;i++) scanf("%d%d%d",&d[i],&l[i],&r[i]);
    if(check(m)) puts("0");
    else 
    {
        int ll=1,rr=m;
        while(ll<rr)
        {
            int mid=ll+rr>>1;
            if(check(mid)) ll=mid+1;
            else rr=mid;
        }
        puts("-1");printf("%d",ll);
    }
    return 0;
}
全部评论

相关推荐

我看标题以为40W,我觉得最差也得40k,点进去一看40块。你永远想不到客户的预算有多低...&nbsp;要求&ldquo;前端使用vue+element开发一个pc端宠物网站和vue+vant开发一个移动端网站,类型是宠物网站的。客户预算40&rdquo;&nbsp;全网最受欢迎的嵌入式面经面经一共32篇文章,12w+字数,包含全部最新的面试必问考点,4.7w+同学学习,2800+订阅,非常适合在找工作面经薄弱的同学,3000+订阅还会涨价,提前订阅提前享受,持续更新中。原帖链接:https://www.nowcoder.com/creation/manager/columnDetail/MJNwoMc
野猪不是猪🐗:哎呀,看来这位客户预算确实挺让人意外的呢!不过,别灰心,有时候客户的预算有限,但项目完成后说不定能带来意想不到的收获呢!😊 至于你提到的嵌入式面经,听起来好像很棒的样子!如果你对求职有帮助,那确实值得订阅学习哦!悄悄告诉你,点击我的头像,我们可以私信聊聊更多求职经验和技巧哦~🎉 对了,你对Vue和Element/Vant的开发有什么疑问或者想要分享的经验吗?我们可以一起探讨一下~😉
点赞 评论 收藏
分享
03-29 12:10
门头沟学院 C++
挣K存W养DOG:散漫消极者淘汰,一眼坑爹。实习几个月转正的时候说你加班太少,能力还行态度不够积极裁了,马上老实。
点赞 评论 收藏
分享
03-21 08:46
已编辑
门头沟学院 C++
只写bug的程序媛:本科能找到好的,真不建议读研,提前占坑比较好,本科找不到好的,也不建议读研,因为两三年之后压力只会更大,唯一的解就是行业好起来
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务