购物(sum)

【from new_dtoj 3966:购物(sum)】
题目描述
visit_world有一个商店,商店里卖N个商品,第i 个的价格为ai{a_i}我们称一个正整数K是美妙的,当且仅当我们可以在商店里选购若干个商品,使得价格之和落在区间[K,2K]中。
问:有多少个美妙的数。
输入
第一行一个整数N。
接下来一行N个整数,描述数组a。
输出
输出一行一个整数,表示答案。
样例输入
3
1 2 3
样例输出
6
提示
解释
可以证明1≤K≤6 都是美妙的,除此之外的数都不是美妙的。
数据范围和子任务
N≤105{10^5},ai{a_i}109{10^9}且为正整数
子任务 1(30 分):N≤100,ai{a_i}≤100 .
子任务 2(20 分):N≤105{10^5},ai{a_i}≤20.
子任务 3(20 分):N≤3,ai{a_i}109{10^9} .
子任务 4(30 分):N≤105{10^5},ai{a_i}109{10^9} .
题解
首先我们先将ai{a_i}从小到大排序,对于每个ai{a_i},它的合法区间是[(ai{a_i}+1)/2,ai{a_i}]
si{s_i}表示前i个数的和
因为最终答案的范围在(a1{a_1}+1)/2到sn{s_n}中,所以我们可以考虑在这个范围内,哪几块的k值也是不能选的,最后减去即可
假设已经处理前i-1次要减去的值,现在考虑第i次要减去什么,这里应该分成两类

  1. (ai{a_i}+1)/2<=si1{s_{i-1}}
    因为 (ai{a_i}+1)/2<=si1{s_{i-1}},所以在(ai{a_i}+1)/2到si1{s_{i-1}}已经处理完全了,而si1{s_{i-1}}~ai{a_i}都是可取的,可以发现ai{a_i}si{s_i}这一块也处理过了,所以在这里并不需要减去什么
  2. (ai{a_i}+1)/2>si1{s_{i-1}}
    同上方类似,唯一不同的是可以发现si1{s_{i-1}}~(ai{a_i}+1)/2中的k值是去不到的,所以要把这一块数的个数减去

具体代码如下

#include <cstdio>
#include <algorithm>
using namespace std;
int n;long long a[100005],m,s,r;
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
    sort(a+1,a+n+1);
    for (int i=1;i<=n;s+=a[i],i++)
        if (((a[i]+1)/2)>s) m-=((a[i]+1)/2)-s-1;
    return printf("%lld\n",m+s),0;
}
posted @ 2018-10-18 16:56  xjqxjq  阅读(167)  评论(0编辑  收藏  举报