zoukankan      html  css  js  c++  java
  • 【NOIP2017提高组模拟12.24】B

    题目

    现在你有N个数,分别为A1,A2,…,AN,现在有M组询问需要你回答。每个询问将会给你一个L和R(L<=R),保证Max{Ai}-Min{Ai}<=R-L,你需要找出并输出最小的K(1<=K<=N,不存在输出-1)满足以下两个条件:
    ①能够在原来的N个数中选出不重复(下标不重复)的K个数,使得这K个数的和在区间[L,R]内。
    ②能够在原来的N个数中选出不重复(下标不重复)的K个数,使得这K个数的和不在区间[L,R]内。

    分析

    首先将A从小到大排个序,那么前k个数的和就是最小的k个数的和,后k个数的和就是最大的k个数的和。
    那么设它们分别为(min(k))(max(k))
    要满足(②),显然只要(min(k)<L)(R<max(k))就可以了;
    考虑(①)
    注意到"保证Max{Ai}-Min{Ai}<=R-L"
    也就是说选的k个数的间隔一定小于(R-L)
    于是(min(k)<L<=max(k))(min(k1)<=R<max(k1))
    那么分别二分(k、k1)的上下界,(l1<=k<=r1、l2<=k1<=r2)
    因为k越小越好,
    所以如果(l1)合法就输出(l1),否则输出(l2)

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const long long maxlongint=2147483647;
    const long long mo=1000000007;
    const long long N=100005;
    using namespace std;
    long long a[N],mx[N],mn[N],n,m;
    int main()
    {
    	scanf("%lld%lld",&n,&m);
    	for(long long i=1;i<=n;i++) scanf("%lld",&a[i]);
    	sort(a+1,a+1+n);
    	for(long long i=1;i<=n;i++) mn[i]=mn[i-1]+a[i],mx[i]=mx[i-1]+a[n-i+1];
    	for(long long i=1;i<=m;i++)
    	{
    		long long l,r;
    		scanf("%lld%lld",&l,&r);
    		long long l1=lower_bound(mx,mx+1+n,l)-mx,r1=lower_bound(mn,mn+1+n,l)-mn-1;
    		long long l2=upper_bound(mx,mx+1+n,r)-mx,r2=upper_bound(mn,mn+1+n,r)-mn-1;
    		if(l1==n+1 || r2==0 || l1>r1 && l2>r2) printf("-1
    ");
    		else
    		{
    			if(l1>r1) printf("%lld
    ",l2);
    			else printf("%lld
    ",l1);
    		}
    		
    	}
    }
    
    
  • 相关阅读:
    (五)TortoiseSVN 客户端-----安装
    (四)svn 服务器端的使用之创建工程目录
    (三)svn 服务器端之创建仓库
    (二)svn服务端安装配置
    (一)svn介绍
    JFinal常量配置学习笔记
    继承、多态、重载和重写
    聊聊基本类型(内置类型)
    日期和时间的处理
    设计模式——享元模式
  • 原文地址:https://www.cnblogs.com/chen1352/p/9071395.html
Copyright © 2011-2022 走看看