• 聪明的质监员


    Description
    小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有n 个矿石,从1到n 逐一编号,每个矿石都有自己的重量wi 以及价值vi。检验矿产的流程是:
    1、给定m 个区间[Li,Ri];
    2、选出一个参数W;
    3、对于一个区间[Li,Ri],计算矿石在这个区间上的检验值Yi :这个区间上所有重量大于等于W的矿石数目与它们的价值和的乘积。这批矿产的检验结果Y 为各个区间的检验值之和。若这批矿产的检验结果与所给标准值S 相差太多,就需要再去检验另一批矿产。小T不想费时间去检验另一批矿产,所以他想通过调整参数W 的值,让检验结果尽可能的靠近标准值S,即使得S-Y 的绝对值最小。请你帮忙求出这个最小值。

    Input
    第一行包含三个整数 n,m,S,分别表示矿石的个数、区间的个数和标准值。
    接下来的 n 行,每行2 个整数,中间用空格隔开,第i+1 行表示i 号矿石的重量wi 和价
    值vi 。
    接下来的 m 行,表示区间,每行2 个整数,中间用空格隔开,第i+n+1 行表示区间[Li,
    Ri]的两个端点Li 和Ri。注意:不同区间可能重合或相互重叠。

    Output
    输出只有一行,包含一个整数,表示所求的最小值。

    Sample Input
    5 3 15 1 5 2 5 3 5 4 5 5 5 1 5 2 4 3 3

    Sample Output
    10

    Data Constraint

    Hint

    【输入输出样例说明】
    当 W 选4 的时候,三个区间上检验值分别为20、5、0,这批矿产的检验结果为25,此时与标准值S 相差最小为10。

    【数据范围】
    对于 10%的数据,有1≤n,m≤10;
    对于 30%的数据,有1≤n,m≤500;
    对于 50%的数据,有1≤n,m≤5,000;
    对于 70%的数据,有1≤n,m≤10,000;
    对于 100%的数据,有1≤n,m≤200,000,0 < wi, vi≤106,0 < S≤1012,1≤Li≤Ri≤n。

    .
    .
    .
    .
    .
    .
    分析
    在这里插入图片描述

    公式解读:>=w的个数*价值和

    大概意思就是说给了几组区间,在区间中选出j个重量大于等于W的矿石
    这一个区间的检验值就为j * (v1 + v2 + …… + vj)
    总的检验值之和Y为所有区间检验值加起来,那么容易得出,W取越小,我们能选的矿石就越多
    检验值也就越大。反之就越小。那我们的任务就变成了求一个W,使得Y最靠近S

    如果用O(n)来求W的话,貌似是不合理的。我们又发现W跟随Y具有单调性,这就变成了类似在单调函数中
    求值的问题,用二分就很好解决。对于每一次计算检验值,显然模拟时间复杂度将会很高
    于是在检验一个W值时,先跑一遍前缀和,满足条件的值加上,不满足条件的不加上
    之后求m个区间的检验值就很容易了

    注意二分的范围还有long long

    .
    .
    .
    .
    .
    程序:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    long long n,m,w[200010],v[200010],maxx=-2147483647,minn=2147483647,ll[200010],rr[200010];
    long long s,sum[200010],num[200010];
    
    int main()
    {
    	scanf("%lld%lld%lld",&n,&m,&s);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%lld%lld",&w[i],&v[i]);
    		maxx=max(maxx,w[i]);
    		minn=min(minn,w[i]);
    	}
    	for (int i=1;i<=m;i++)
    		scanf("%lld%lld",&ll[i],&rr[i]);
    	long long l=minn,r=maxx;
    	long long ans=0X7fffffffffffffff;
    	while (l<=r)
    	{
    		long long mid=(long long)((long long)l+r)/2;
    		memset(sum,0,sizeof(sum));
    		memset(num,0,sizeof(num));
    		for (int i=1;i<=n;i++)
    			if (w[i]>=mid)
    			{
    				sum[i]=(long long)sum[i-1]+v[i];
    				num[i]=num[i-1]+1;
    			} else
    			{
    				sum[i]=sum[i-1];
    				num[i]=num[i-1];
    			}
    		long long tj=0;
    		for (int i=1;i<=m;i++)
    			tj=(long long)tj+(long long)((long long)num[rr[i]]-num[ll[i]-1])*((long long)sum[rr[i]]-sum[ll[i]-1]);
    		long long jg=abs((long long)s-tj);
    		if (jg<ans) ans=jg;
    		if (tj>=s) l=mid+1;
    		if (tj<s) r=mid-1;
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    scikit-learn
    caffe
    大型云原生项目在数字化企业落地过程解密
    「澳洋主数据项目」主数据促企业变革
    Docker镜像仓库清理的探索之路
    用友云开发者中心助你上云系列之在线调试
    如何精简企业主数据“裹脚布”
    企业推动移动化战略中为什么需要Moli?
    欧派家居牵手用友云平台 打造标准化数据资产管理平台
    用友云开发者中心,你应该知道的那些事
  • 原文地址:https://www.cnblogs.com/YYC-0304/p/10292782.html
Copyright © 2020-2023  润新知