0
点赞
收藏
分享

微信扫一扫

洛谷P1314聪明的质检员(前缀和加二分

如果s大于了y,那么就把y变大,w变小,反之变大。经典while(left<=right)

记得更新sum 和ans

#include<bits/stdc++.h>
using namespace std;
int n,m;
int ans;
long long s;long long sum;
long long y=0;
long long qz[900010],qzn[900010];
int w[900010],v[900010],l[900010],r[900010];
bool check(int mid)
{	
y=0,sum=0;
	memset(qz,0,sizeof(qz));
	memset(qzn,0,sizeof(qzn));
	for(int i=1;i<=n;i++)
	{
		if(w[i]>=mid)
		{
			qz[i]=qz[i-1]+v[i];
			qzn[i]=qzn[i-1]+1;
		}
		else
		{
			qz[i]=qz[i-1];
			qzn[i]=qzn[i-1];
		}
	}
	for(int i=1;i<=m;i++)
	{
		y+=(qz[r[i]]-qz[l[i]-1])*(qzn[r[i]]-qzn[l[i]-1]);
	}
	sum=llabs(y-s);
	if(y>s)
	{
		return true;
	}
	else
	{
		return false;
	}
}
int main()
{
long long ans=0x3f3f3f3f3f3f3f3f;
	scanf("%d%d%lld",&n,&m,&s);
	int left=2147483647,right=-1;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&w[i],&v[i]);
		left=min(left,w[i]);
		right=max(right,w[i]);
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&l[i],&r[i]);
	
	}
	left=left-1;
	right=right+2;
	while(left<=right)
	{
		int mid=(left+right)/2;
		if(check(mid))
		{
		  left=mid+1;
		}
		else
		{
			right=mid-1;
		}
		if(sum<ans)
		ans=sum;
	}
	printf("%lld",ans);
}

本题的前缀和虽然是相乘后的前缀和,但也差不多。

举报

相关推荐

0 条评论