刚学c++1毫秒——5分过了最后一个点求助
查看原帖
刚学c++1毫秒——5分过了最后一个点求助
600186
lcx20081002c楼主2025/2/5 11:52
#include<bits/stdc++.h>//题意:y每个区间=区间内质量大于M矿石数量*区间内矿石价值和,y=m个区间y值的和,要求y-s绝对值的最小 
using namespace std;
long long n,m,s,ss,ans=0;//n个矿石,m个区间,标准值为s,最小为ss,某一次算的为ans 
pair<long long,long long>pp[200005]; long long sum[200005],sup[200005];//质量,价值,前缀和(质量和价值) 
pair<long long,long long>p[200005];//区间左边,区间右边 
bool check(long long);
long long minn(long long,long long);
int main()
{
	cin>>n>>m>>s;
	for(int i=1;i<=n;i++)
	    cin>>pp[i].first>>pp[i].second;
	for(int i=1;i<=m;i++)
	    cin>>p[i].first>>p[i].second;
	ss=s;
	cout<<minn(0,2*s);//随着W增大,yi和y单调不增 
	return 0;
}	
bool check(long long x)
{
    memset(sum,0,sizeof(sum));
	memset(sup,0,sizeof(sup));
	ans=0;
	for(int i=1;i<=n;i++) 
	{
		if(pp[i].first>=x)
		{
			sum[i]=sum[i-1]+1;
			sup[i]=sup[i-1]+pp[i].second;//计算前缀和,就是把从1加到i的数量和、价值和算出来,方便后面可用相减完成任意两个序号间矿石价值计算 
		}
		else
		{
			sum[i]=sum[i-1];
			sup[i]=sup[i-1];//他们管这叫维护,就是修正前缀和计算的漏洞 
		}
		
	}
	for(int i=1;i<=m;i++)
	    ans+=(sum[p[i].second]-sum[p[i].first])*(sup[p[i].second]-sup[p[i].first]);	
	long long k=ans;
	ans=abs(k-s);
	if(k>=s)
	    return true;
	return false;
}
long long minn(long long l,long long r)
{
	
	while(l<r)
	{
		int mid=l+r+1>>1;
		if(check(mid))
		    l=mid;
		else
		    r=mid-1;
		ss=min(ss,ans);
	}
	return ss;
}
2025/2/5 11:52
加载中...