[NOIp2012] luogu P1083 借教室

该*的英语,这么长还要背。

题目描述

你有 n n n 个数 a i {a_i} ai m m m 次操作,每次操作将 [ l , r ] [l,r] [l,r] 区间的每个数减去 c c c。要求任何时刻 ∀ x ∈ [ 1 , n ] \forall x\in[1,n] x[1,n] 都有 a i ≥ 0 a_i\geq0 ai0,请你告诉我最多可以合法地执行多少次操作。

Solution

很明显这是个差分数组对吧。

二分答案即可,每次线性地判断该状态是否合法。时间复杂度 O ( n log ⁡ m ) O(n\log m) O(nlogm)

#include<cstdio>
#include<cstdlib>
#include<cstring>

const int MAXN=1000010;

int n,m;
int d[MAXN],D[MAXN];
int sx[MAXN],sy[MAXN],sd[MAXN];

int check(int x){
	for(int i=1;i<=n;++i)
		d[i]=D[i];
	for(int i=1;i<=x;++i){
		d[sx[i]]-=sd[i];
		d[sy[i]+1]+=sd[i];
	}
//	printf("%d\t",x);
//	for(int i=1;i<=n;++i)
//		printf("%d ",d[i]);
//	puts("");
	int tmp=0;
	for(int i=1;i<=n;++i){
		tmp+=d[i];
		if(tmp<0) return 0;
	}
	return 1;
}
inline int read(){
	int x=0; char c;
	do c=getchar(); while(c<'0'||c>'9');
	while(c>='0'&&c<='9')
		x=x*10+c-48,c=getchar();
	return x;
}
int main(){
	n=read();m=read();d[0]=0;
	for(int i=1;i<=n;++i){
		d[i]=read();
		D[i]=d[i]-d[i-1];
	}
	for(int i=1;i<=m;++i){
		sd[i]=read();
		sx[i]=read();
		sy[i]=read();
	}
	int l=0,r=n,mid,ans=-1;
	while(l<=r){
		mid=(l+r)/2;
		if(check(mid)){
			ans=mid;
			l=mid+1;
		}
		else
			r=mid-1;
	}
	puts(ans==n?"0":"-1");
	if(ans!=n) printf("%d",ans+1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值