【题解】洛谷P1314 聪明的质检员(前缀和 二分 数学)

还是没想出来正解。。不过题解一看就会系列qaq

同类型的题还得多练

https://www.luogu.org/blog/codinging/solution-p1314

注:代码里的最大值不够大只有50分 建议开的大一点 亲测1e15可以过

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define ll long long
using namespace std;
const int maxn=200010;
int n,m;
ll s;
struct stein
{
	ll w;
	ll v;
}a[maxn];
int l[maxn],r[maxn];
ll y,sum;
ll tot,ans=1e9;
ll minw=1e9,maxw=-1e9;
ll sumn[maxn],sumv[maxn];
int lft=0,rht=0,mid;
bool check(int W)
{
	y=0,sum=0;
	memset(sumn,0,sizeof(sumn));
	memset(sumv,0,sizeof(sumv));
	for(int i=1;i<=n;i++)
	{
		if(a[i].w>=W)
		{
			sumn[i]=sumn[i-1]+1;
			sumv[i]=sumv[i-1]+a[i].v;
		}
		else
		{
			sumn[i]=sumn[i-1];
			sumv[i]=sumv[i-1];
		}
	}
	for(int i=1;i<=m;i++)
	{
		y+=(sumn[r[i]]-sumn[l[i]-1])*(sumv[r[i]]-sumv[l[i]-1]);
	}
	sum=abs(y-s);
	if(y>s) return true;
	else return false;
}
int main()
{
	scanf("%d%d%lld",&n,&m,&s);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&a[i].w,&a[i].v);
		minw=min(minw,a[i].w);
		maxw=max(maxw,a[i].w);
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&l[i],&r[i]);
	}
	lft=minw-1,rht=maxw+2;
	while(lft<=rht)
	{
		mid=(lft+rht)/2;
		if(check(mid)) lft=mid+1;
		else rht=mid-1;
		if(sum<ans) ans=sum; 
	}
	printf("%lld",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Rem_Inory/article/details/81809035