购物(sum)

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

  1. ( a i {a_i} +1)/2<= s i 1 {s_{i-1}}
    因为 ( a i {a_i} +1)/2<= s i 1 {s_{i-1}} ,所以在( a i {a_i} +1)/2到 s i 1 {s_{i-1}} 已经处理完全了,而 s i 1 {s_{i-1}} ~ a i {a_i} 都是可取的,可以发现 a i {a_i} s i {s_i} 这一块也处理过了,所以在这里并不需要减去什么
  2. ( a i {a_i} +1)/2> s i 1 {s_{i-1}}
    同上方类似,唯一不同的是可以发现 s i 1 {s_{i-1}} ~( a i {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;
}

猜你喜欢

转载自blog.csdn.net/Johnny817/article/details/83149426
sum