1. 程式人生 > >Noip2012-借教室

Noip2012-借教室

這個題首先很容易想到列舉1-m,再一個一個加起來,判斷一下(最直白的暴力)

於是又很容易想到用差分陣列可以優化一下。

就像這樣

#include <iostream>
#include <cstdio>

using namespace std;
const int maxn=1000005;
int d[maxn],s[maxn],t[maxn],r[maxn];
int c[maxn];int n,m; 
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&r[i]);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&d[i],&s[i],&t[i]);
	}
	for(int i=1;i<=m;i++)
	{
		c[s[i]]+=d[i];c[t[i]+1]-=d[i];
		int sum=0;
		for(int j=1;j<=n;j++)
		{
			sum+=c[j];if(sum>r[j]) 
				{cout<<"-1"<<endl<<i<<endl;return 0;}
		} 
	}
	cout<<0<<endl;
	return 0;
}

然而這樣只有40分。。。

我們又發現外層循換i=1-m是滿足單調性的

SO,可以二分一下x(x是指1-x都滿足條件)

就很愉快的ac了

#include <iostream>
#include <cstdio>
#include <cstring>
 
using namespace std;
const int maxn=1000005;
int d[maxn],s[maxn],t[maxn],r[maxn];
int c[maxn];int n,m;
int ok(int x)
{
	memset(c,0,sizeof(c));
	for(int i=1;i<=x;i++)
	{
		c[s[i]]+=d[i];c[t[i]+1]-=d[i];	
	} 
	int sum=0;
	for(int i=1;i<=n;i++)
	{
		sum+=c[i];if(sum>r[i]) return 0;
	}
	return 1;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&r[i]);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&d[i],&s[i],&t[i]);
	}
	int l=0,r=m;int ans=-1;
	while(l<=r)
	{
		int mid=(l+r)/2;
		if(ok(mid)) {ans=mid;l=mid+1;}
		else r=mid-1;
	}
	//printf("%d",ans);
	if(ans==m) {printf("%d\n",0);}
	else {printf("-1\n%d",ans+1);}
	return 0;
 }