解题思路:
如何选择购买是与顺序无关的,我们发现,排序后,如果选择购买的商品价格高,那么可以选价格相对更高的商品报销,这样就可以降低成本 。排序后,贪心的从后往前购买商品,当购买的商品数量达到2时,就可以选择一个商品报销,毫无疑问我们需要在能报销的范围内找最大报销,也就是在0~a[i]/2下取整范围中找。如果我们按循环一个一个去找那么时间复杂度会达到o(n^2),会超时,这个方法不可取。注意到我们事先进行了排序,那么就可以二分查找的方式找到最大的<=a[i]/2的值,记录报销此产品,最后统计答案时忽略该值。
注意事项:
当我们二分出一个可以报销的价格时,我们标记改值,次商品不用再购买也不能再报销,我们可以发现,这个商品的后面的商品是都不能在继续买商品报销的,因为这个临界点是我们二分出来的,此时把下一次二分右端点往左移一位,为下一次二分出临界点做前置条件。
参考代码:
import java.util.*;
import java.io.*;
public class Main {
static int[] dx = {0,1,-1,0};
static int[] dy = {1,0,0,-1};
static long qmi(long a,long k,long mod)
{
long res = 1;
while(k>0)
{
if(k%2==1) res = (res*a)%mod;
k >>= 1;
a = (a*a)%mod;
}
return res;
}
public static void main(String[] args) {
InputReader in = new InputReader(System.in);
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
int n = in.nextInt();
int[] a = new int[n];
for(int i = 0; i < n;i ++)
a[i] = in.nextInt();
long res = 0;
boolean[] v = new boolean[n];
int f = 0;
Arrays.sort(a);
int k = n-1;
for(int i = n-1;i >= 0;i --)
{
if(v[i]) continue;
f ++;
if(f == 2)
{
int l = 0;int r = k;
while(l < r)
{
int mid = l+r+1>>1;
if(a[mid]*2<=a[i])
l = mid;
else r = mid-1;
}
if(a[l]*2<=a[i])
{
v[l] = true;//二分出的点可以报销,标记此点不需要统计答案;
k = l-1;//二分临界端点左移
}
f = 0;
}
}
for(int i = 0;i < n;i ++) if(!v[i]) res += a[i];//统计没有标记的答案,被标记过的都是报销价格的。
out.println(res);
out.flush();
}
}
class InputReader {
private final BufferedReader buf;
private StringTokenizer tkl;
public InputReader(InputStream is) {
buf = new BufferedReader(new InputStreamReader(is));
}
public boolean hasNext() {
try {
while (tkl == null || !tkl.hasMoreElements()) tkl = new StringTokenizer(buf.readLine());
} catch (Exception e) {
return false;
}
return true;
}
public String next() {
return hasNext() ? tkl.nextToken() : null;
}
public int nextInt() {
return Integer.parseInt(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
public long nextLong() {
return Long.parseLong(next());
}
}
0.0分
1 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复