3 solutions

  • 0
    @ 2024-1-6 18:44:21

    【在线】【分块】 借教室

    题意: 共有n天,每天可以用于借出的教室的数量为 a[i] ,有m个订单,每个订单每天都有相同的借教室的需求。借教室按照先来后到的原则,所以可能后续的订单无法满足,如果有就输出无法满足的那一个订单编号,反之都能满足就输出-1.

    分析: 分块和线段树同样是相似的做法,思路几乎一样同样维护最小值,每次修改完区间后看区间最小值-lazy是不是小于零就可以了 。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e6+12;
    int n,m;
    int tot,L[N],R[N],block,a[N],lazy[N],belong[N],mi[N],l,r,x;
    void build()
    {
      block=sqrt(n);
      tot=n/block;
      if( n%block ) tot++;
      for(int i=1;i<=n;i++)
      {
        belong[i]=(i-1)/block+1;
        mi[ belong[i] ]=min( mi[belong[i]],a[i] );
      }
      for(int i=1;i<=tot;i++)
      {
        L[i]=(i-1)*block+1,R[i]=i*block;
      }
      R[tot]=n;
    }
    void add(int x,int y,int v,int now)
    {
      int  ans=1;
      if( belong[x]==belong[y] )
      {
        for(int i=x;i<=y;i++)
        {
          a[i]-=v;
          ans=min(ans,a[i]-lazy[belong[i]]);
          mi[belong[i]]=min(mi[belong[i]],a[i]);
        }
      }
      else{
        for(int i=x;i<=R[belong[x]];i++)
        {
          a[i]-=v;
          ans=min(ans,a[i]-lazy[belong[i]]);
          mi[belong[i]]=min(mi[belong[i]],a[i]);
        }
    
        for(int i=belong[x]+1;i<belong[y];i++)
        {
          lazy[i]+=v;
          ans=min(ans, mi[i]-lazy[i] );
        }
        for(int i=L[belong[y]];i<=y;i++)
        {
          a[i]-=v;
          ans=min( ans,a[i]-lazy[belong[i]] );
          mi[ belong[i] ]=min( mi[belong[i]],a[i] );
        }
      }
      if( ans<0 ) {
        cout<<-1<<endl<<now;
        exit(0);
      }
      return;
    }
    int main(){
    
      cin>>n>>m;
      for(int i=1;i<=n;i++) mi[i]=2000000012;
      for(int i=1;i<=n;i++) cin>>a[i];
      build();
      for(int i=1;i<=m;i++)
      {
          cin>>x>>l>>r;
          add(l,r,x,i);
      }
      cout<<0;
    }
    
    

    Information

    ID
    10552
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    10
    Tags
    # Submissions
    8
    Accepted
    3
    Uploaded By