[NOIP2012提高组]借教室

Posted Mrsrz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOIP2012提高组]借教室相关的知识,希望对你有一定的参考价值。

题目:洛谷P1083、Vijos P1782、codevs1217。

题目大意:有n天,每天可以借a[i]个教室。有m个请求,每个请求要在一段连续天数内借固定数目的教室。请求只能按顺序批准。求第一个无法批准的请求是第几个请求,或全部可以批准。

解题思路:看到区间,容易想到线段树维护(正解貌似是二分,燃鹅我只能理解线段树啊~)。这里显然只需维护最小值。不过如果姿势不好,可是会T的哟。

线段树肯定很好写,但想不超时,就得优化。例如读入优化、标记永久化、递归过程能用全局变量用全局变量、搜到答案直接退出等。最后提交,坐等AC即可。

C++ Code:

#include<cstdio>
#include<cstdlib>
#include<cctype>
using namespace std;
long long d[4000005],p[4000005];
int i,n,m,L,R,k;
inline long long min(long long a,long long b){return(a<b)?a:b;}
inline int readint(){
	char c=getchar();
	int p=0;
	for(;!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar())p=(p<<3)+(p<<1)+(c^‘0‘);
	return p;
}
void make_tree(int l,int r,int o){
	p[o]=0;
	if(l==r){
		d[o]=readint();
		return;
	}
	int mid=l+r>>1,lf=o<<1,rg=o<<1|1;
	make_tree(l,mid,lf);
	make_tree(mid+1,r,rg);
	d[o]=min(d[lf],d[rg]);
}
void change(int l,int r,int o){
	if(L<=l&&r<=R){
		p[o]+=k;
		if(d[o]-p[o]<0){
			printf("-1\n%d\n",i);
			exit(0);
		}
		return;
	}
	int mid=l+r>>1,lf=o<<1,rg=o<<1|1;
	if(L<=mid)change(l,mid,lf);
	if(mid<R)change(mid+1,r,rg);
	d[o]=min(d[lf]-p[lf],d[rg]-p[rg]);
	if(d[o]-p[o]<0){
		printf("-1\n%d\n",i);
		exit(0);
	}
}
int main(){
	n=readint(),m=readint();
	make_tree(1,n,1);
	for(i=1;i<=m;++i){
		k=readint(),L=readint(),R=readint();
		change(1,n,1);
	}
	puts("0");
	return 0;
}

 

以上是关于[NOIP2012提高组]借教室的主要内容,如果未能解决你的问题,请参考以下文章

[NOIP2012提高组]借教室

NOIP提高组2012 借教室

NOIP2012提高组 Day 2 Problem 2 借教室

noip2012——提高组——借教室

洛谷P1083 [NOIP2012提高组Day2T2]借教室

二分查找or线段树(借教室洛谷1083vijos1782NOIP 2012 提高组 第二天 第二题)