洛谷P1314 聪明的质监员(NOIP 2011)

题目描述 https://www.luogu.org/problemnew/show/P1314
找合适的w使差值最小,二分
直接搜的话会超时,要用前缀和

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int l=2147483647,r=-1,n,m;
int v[N],w[N],b[N],t[N];
ll s,ans=1e115+5,sum,sv[N],sn[N];
bool jud(int x)
{
	ll tmp=0;
	memset(sv,0,sizeof(sv));
	memset(sn,0,sizeof(sn));
	for(int i=1;i<=n;i++)
	{
	   if(w[i]>=x) sv[i]=sv[i-1]+v[i],sn[i]=sn[i-1]+1;
	   else sv[i]=sv[i-1],sn[i]=sn[i-1];
	}
	for(int i=1;i<=m;i++) 
	  tmp=tmp+(sn[t[i]]-sn[b[i]-1])*(sv[t[i]]-sv[b[i]-1]);  
	sum=abs(tmp-s);
	if(tmp>s) return 1;
	else return 0;
}
int main()
{ 	
	scanf("%d%d%lld",&n,&m,&s);
	for(int i=1;i<=n;i++) 
	{
	   scanf("%d%d",&w[i],&v[i]);
	   l=min(l,w[i]),r=max(r,w[i]);
	}
	for(int i=1;i<=m;i++) scanf("%d%d",&b[i],&t[i]);
	l-=1,r+=2;
	while(l<=r)
	{
		int mid=(l+r)/2;
		if(jud(mid)) l=mid+1;
		else r=mid-1;
		if(sum<ans) ans=sum;
	}
	printf("%lld",ans);
	
  return 0;	
}

猜你喜欢

转载自blog.csdn.net/qq_42920122/article/details/88694469