借教室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