[JZOJ4932] B

来源:互联网 发布:通联数据招聘 编辑:程序博客网 时间:2024/06/10 15:02

Description

现在你有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]内。
这里写图片描述

Solution

先考虑能满足②的。
先把A排个序
求出每个k能选出的最大值、最小值,显然就是排序后的前后k个。

分别设为min[k],max[k],显然它是单调的。
那么显然,只要有一个在L,R之外的就合法。

考虑①

注意到题目里有一句话

Max{Ai}-Min{Ai}<=R-L

什么意思呢?就是说,任意两个Ai的差值一定小于RL
也就是说,排序后相邻的两种的差异一定不会同时跨过L,R

也就是说,只要[min[k],max[k]]这个区间与[L,R]有交集,那么就一定满足①

那么既要有交集,又要有一个在L,R之外。

那就是max[k]L>min[k]max[k]>Rmin[k]
那么这四个不等式,分别对应着四个k的边界l1,r1,l2,r2,l1<r1<l2<r2,显然这四个边界可以二分出来。

[l1,r1],[l2,r2]是合法的
如果左边能满足,那就选l1,如果左边没有而右边有,那就选l2

Code

#include <cstdio>#include <cstdlib>#include <algorithm>#include <iostream>#include <cstring>#include <cmath>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)#define LL long long #define N 100005#define lb lower_bound#define ub upper_boundusing namespace std;LL a[N],mi[N],ma[N];int n,m;int main(){    cin>>n>>m;    LL s=0,s1=0;    fo(i,1,n) scanf("%lld",&a[i]),s+=a[i];    sort(a+1,a+n+1);    ma[n]=mi[n]=s;    fo(i,1,n)    {        s1+=a[i];        mi[i]=s1;        ma[n-i]=s-s1;    }    ma[0]=mi[0]=0;    fo(i,1,m)    {        LL l,r;        scanf("%lld%lld",&l,&r);        int l1=lb(ma,ma+n+1,l)-ma,r1=lb(mi,mi+n+1,l)-mi-1,l2=ub(ma,ma+n+1,r)-ma,r2=ub(mi,mi+n+1,r)-mi-1;        if(l1==n+1||r2==0||(l1>r1&&l2>r2)) printf("-1\n");        else         {            if(l1<=r1) printf("%d\n",l1);            else printf("%d\n",l2);        }       }}
1 1
原创粉丝点击