2 条题解

  • 3
    @ 2023-2-28 18:11:48

    二分题 我们首先要找二分对象 很容易想到,应该按每一天的订单二分 问题来了,check函数怎么写 首先,我们需要一个前缀和的预处理,也就是把每一天需要的教室都算出来(我有注释) 然后我们只需要比较每一天所需要的和剩余的就行了 有两个需要注意的点 一个是要特判最后一天能否完成,如果能那就肯定够 第二个是每一次求前缀和的时候都需要清零 这里就不得不提STL的vector了,O(1)复杂度直接清零,轻轻松松不怕超时 那么到这里这道题就解决了 顺便一提 STL库的容器蒸的很好用!!!(龙叔音)

    #include<bits/stdc++.h>
    using namespace std;
    int a[1000001],k[1000001];
    vector<int>z(1000001);
    int n,m;
    struct apply{
    	int num1,begin1,end1;
    }h[1000001];
    bool check(int y)
    {
    	z.clear();//清空 
    	z.resize(1000001);//重设 
    	for(int i=1;i<=y;i++)//求前缀和 
    	{
    		z[h[i].begin1]+=h[i].num1;//这一天所需的 
    		z[h[i].end1+1]-=h[i].num1;//当天结束了的要减去(+1是因为结束的那一天会多算一次(自己那笔模拟一下 
    	}
    	for(int i=1;i<=n;i++)
    	{
    		k[i]=k[i-1]+z[i];//当天所需的 
    		if(k[i]>a[i]) return false;//需要的大于剩余的当然就不行了 
    	}
    	return true;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    	{
    		int x;
    		scanf("%d",&x);
    		a[i]=x;
    	}
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&h[i].num1,&h[i].begin1,&h[i].end1);
    	}
    	int l=1,r=m;
    	if(check(m))//如果最后一天的订单可以,那就都可以 ,算一个小特判 
    	{
    		cout<<"0";
    		return 0;
    	}
    	while(l<r)//二分 
    	{
    		int mid=(l+r)/2;
    		if(check(mid)) l=mid+1;
    		else r=mid;
    	}
    	cout<<"-1"<<endl<<r; 
    	return 0;
    }
    

    信息

    ID
    205
    时间
    1000ms
    内存
    256MiB
    难度
    7
    标签
    递交数
    62
    已通过
    15
    上传者