【NOIP2017提高组模拟12.24】B
2016-12-31 16:00
351 查看
题目
现在你有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 ,mx ,mn ,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\n"); else { if(l1>r1) printf("%lld\n",l2); else printf("%lld\n",l1); } } }
相关文章推荐
- 【NOIP2017提高组模拟12.24】C
- 【NOIP2017提高组模拟12.24】C
- 【NOIP2017提高组模拟12.24】B
- 【NOIP2017提高A组模拟9.14】生命之树 trie+启发式合并
- 【NOIP2017提高组模拟6.25】总结
- JZOJ5393【NOIP2017提高A组模拟10.5】Snake vs Block DP
- 【NOIP2017提高A组模拟7.8】为了爱情 八数码拓展
- 【NOIP2017提高组模拟12.10】幻魔皇
- 【NOIP2017提高组模拟12.18】B
- NOIP2017提高组模拟22-雅礼国庆10.5
- 【JZOJ 4931】【NOIP2017提高组模拟12.24】A
- JZOJ5358【NOIP2017提高A组模拟9.12】BBQ
- JZOJ 100035【NOIP2017提高A组模拟7.10】区间
- 【NOIP2017提高A组模拟7.13】第K小数
- 【NOIP2017提高A组模拟10.8】Star Way To Heaven(欧几里得距离最小生成树Prim做法)
- 【NOIP2017提高组模拟12.18】C
- JZOJ 4932. 【NOIP2017提高组模拟12.24】B
- NOIP2017提高组模拟19 /10.31
- 【JZOJ 4931】【NOIP2017提高组模拟12.24】A
- JZOJ 4933. 【NOIP2017提高组模拟12.24】C