• H小明买年糕(前缀和+二分)


    Description

    过年了,小明准备去超市买年糕,超市里共有nn种年糕,每种年糕数量无限多,从1~n编号,每种年糕有自己的价格wiwi和美味值vivi。小明选购年糕的过程如下:

    1、小明打算去买m次年糕,每次选购区间[Li, Ri][Li,Ri]内的年糕,每种年糕每次只能买一个;

    2、每次选购都用事先准备好的购物袋,购物袋可以装任意数量的物品,但是这个购物袋只装价格wiwi不小于WW的年糕,区间内所有满足条件的年糕都必须要买;

    3、每次出去购买年糕都会产生一个幸福值YiYi,它的计算的公式为:

    Y_i=(sumlimits_{j=L_i}^{R_i}[w_jgeq W] imes v_j) imes (sumlimits_{j=L_i}^{R_i}[w_jgeq W])Y
    i
    ​ =(
    j=L
    i


    R
    i

    ​ [w
    j
    ​ ≥W]×v
    j
    ​ )×(
    j=L
    i


    R
    i

    ​ [w
    j
    ​ ≥W]),其中符号[条件]的意思是:若条件为真,值就是1,否则值就是0;

    所以小明m次选购年糕行动所产生的总幸福值为:H=Y_1+Y_2+…+Y_mH=Y
    1
    ​ +Y
    2
    ​ +…+Y
    m
    ​ ;

    小明是一个精简持家的程序员,所以他选购年糕有一个标准值SS。他想通过调整事先准备的购物袋的WW值,让年糕总幸福值尽量接近SS,即使得S-HS−H的绝对值最小。现在请你帮忙调整购物袋的WW值,使得|S-H|∣S−H∣绝对值最小,并输出这个最小值。

    20190220213730804.jpeg

    Input

    第一行包括三个整数nn, mm, SS,分别表示年糕的种类,购物的次数和标准值。

    接下来nn行,每行两个整数w_iw
    i
    ​ , v_iv
    i
    ​ ,中间用空格隔开,表示第ii个年糕的价格w_iw
    i
    ​ 和美味值v_iv
    i
    ​ 。

    接下来mm行,每行两个整数L_iL
    i
    ​ , R_iR
    i
    ​ ,中间用空格隔开,表示第ii次购物选购区间[L_i, R_i][L
    i
    ​ ,R
    i
    ​ ]的年糕。

    1leq n,mleq 200000, 1leq wi,vileq 1e6, 1leq Sleq 1e12, 1leq Lileq Rileq n1≤n,m≤200000,1≤wi,vi≤1e6,1≤S≤1e12,1≤Li≤Ri≤n

    Output

    一个整数,表示所求最小值。

    Sample Input 1

    5 3 15
    1 5
    2 5
    3 5
    4 5
    5 5
    1 5
    2 4
    3 3
    Sample Output 1

    10
    Hint

    当WW为4时,三次购物的幸福值分别为20,5,020,5,0,年糕的幸福值为2525,此时与标准值SS相差为1010,这是最优情况.

    Source

    2019年集训队选拔赛

    思路:前缀的差分和构成二分的判断条件,是洛谷上一道原题。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    
    using namespace std;
    const int maxn=200010;
    int w[maxn],v[maxn],l[maxn],r[maxn];
    long long p_n[maxn],p_v[maxn];
    long long Y,s,sum;
    int n,m;
    long long mx=-1,mn=1e18;
    
    long long Max(long long a,long long b)
    {
    	return a>b?a:b;
    }
    long long Min(long long a,long long b)
    {
    	return a<b?a:b;
    }
    bool check(int W)
    {   
    	Y=0,sum=0;
    	memset(p_n,0,sizeof(p_n));
    	memset(p_v,0,sizeof(p_v));
    	for(int i=1;i<=n;i++)
    	{
    		if(w[i]>=W) p_n[i]=p_n[i-1]+1,p_v[i]=p_v[i-1]+v[i];
    		else 
    			p_n[i]=p_n[i-1],p_v[i]=p_v[i-1];
    	}
    	for(int i=1;i<=m;i++)
    		Y+=(p_n[r[i]]-p_n[l[i]-1])*(p_v[r[i]]-p_v[l[i]-1]);
    
    	sum=llabs(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(" %d %d",&w[i],&v[i]);
    		mx=Max(mx,w[i]);
    		mn=Min(mn,w[i]);    
    	}
    	for(int i=1;i<=m;i++)
    		scanf(" %d %d",&l[i],&r[i]);
    	int left=mn-1,right=mx+2,mid;  
    	long long ans=999999999999999;
    	while(left<=right)
    	{
    		mid=(left+right)>>1;
    		if(check(mid))  left=mid+1;
    		else right=mid-1;
    		if(sum<ans) ans=sum;
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    Appium Android 元素定位方法 原生+H5
    Eclipse下Python的MySQLdb的安装以及相关问题
    Python模块包中__init__.py文件的作用
    如何调用另一个python文件中的代码
    Python单元测试框架unittest使用方法讲解
    python利用unittest进行测试用例执行的几种方式
    python随机生成手机号码
    eclipse 安装python后pydev不出现
    Appium 如何模拟返回按键
    python分布式进程
  • 原文地址:https://www.cnblogs.com/tomjobs/p/10617588.html
Copyright © 2020-2023  润新知