其他分享
首页 > 其他分享> > 借教室NOIP2012

借教室NOIP2012

作者:互联网

题目:

 

 

 这道题目就是差分加二分答案。

先看为什么能差分,因为题目中的从s[j]借到t[j]就相当于对一个区间进行操作;再看为什么能二分,废话有单调性啊因为可以借n个教室那也可以借n个以下的教室,相反如果不能借n个教室也就不能借n个以上的教室。

再来讲程序,先将n,m.....(一大堆读进来)

再来说关键函数isok(x)返回一表示可以借x个教室,0相反。

isok函数

他先把diff(差分数组)清零,然后更新这个差分数组。

再用更新的diff来更新need数组(这两步操作是求总共有几个借教室的如果大于need[i],在i时空闲的教室数return 0,不行)

最后return 1;

不行的已在上述循环中return 0了

在主程序中,优化if(isok(m)) cout<<"0";return 0;       懂得都懂。

最后套二分模板即可(main)

程序:

#include<bits/stdc++.h>
using namespace std;
const int N=1000011;
int n,m;
long long diff[N];
long long need[N]={0},l[N]={0},r[N]={0},d[N]={0},rest[N];
bool isok(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++)
    {
        need[i]=need[i-1]+diff[i];
        if(need[i]>rest[i]) return 0;
    }
    return 1;
}
int main()
{
#ifdef LOCAL
    freopen( "1.in", "r", stdin );
    freopen( "1.out", "w", stdout );
#endif
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&rest[i]);
    for(int i=1;i<=m;i++) scanf("%d%d%d",&d[i],&l[i],&r[i]);
    if(isok(m))
    {
        cout<<"0";
        return 0;
    }
    int begin=1,end=m;
    while(begin<end)
    {
        int mid=(begin+end)/2;
        if(isok(mid)==1) begin=mid+1;
        else end=mid;
    }
    cout<<"-1"<<endl<<begin;
    return 0;
}

 

标签:return,NOIP2012,int,isok,教室,long,diff
来源: https://www.cnblogs.com/wjk53233/p/16541829.html