CodeVS 1432-总数统计

原题

题目描述 Description

给出n个数,统计两两之和小于k的方案数之和。

输入描述 Input Description

第一行一个数n,表示数字的个数;
第二行到第n + 1行,每行一个不超过2,000,000,000的数k;
第n + 2行一个数m,表示m个问题;
第n + 3行到第n + m + 2行,每行一个数m,询问表示n中两两组合不超过m的组
合的个数;

输出描述 Output Description

输出m行,每行对应一个答案

样例输入 Sample Input

3

1

2

3

2

2

3

样例输出 Sample Output

0

1

数据范围及提示 Data Size & Hint

30%的数据1 ≤ n ≤ 100, 1 ≤ m ≤ 50, k ≤ 2000;
100%的数据 1 ≤ n ≤ 10000, 1 ≤ m ≤ 100, k ≤ 2,000,000,000

题解

刚开始看到前面以为是道水题,想打个打暴力水过,看到后面数据怂了,只好再想优化方法。。。

后来还是想到了二分法,但输入时是无序的,要先敲一个快排从小到大排,接着二分是关键。

设一个函数find(l,r,x),表示区间[l,r]中,不超过x的最大值的位置。

接着在每次读入k的时候,求出区间[1,n]中不超过k的最大值的位置p【这步其实不要也可以,只是效率更高】,接着用一个j循环1~p,每次求出find(j,p+1,k-a[j])-j【也就是能与a[j]结成对子的方案数】,再更新ans,输出。

 1 var a:array[1..10000] of int64;
 2 var n,m,k,p,ans:int64;
 3 var i,j:longint;
 4 function find(l,r,x:int64):int64;//二分
 5 var mid:int64;
 6 begin
 7   while l+1<r do
 8   begin
 9     mid:=(l+r) div 2;
10     if a[mid]<=x then l:=mid else r:=mid;
11   end;
12   exit(l);
13 end;
14 procedure q(l,r:longint);
15 var i,j,m,t:longint;
16 begin
17   i:=l;j:=r;
18   m:=a[(l+r) div 2];
19   repeat
20     while a[i]<m do inc(i);
21     while a[j]>m do dec(j);
22     if i<=j then
23     begin
24       t:=a[i];a[i]:=a[j];a[j]:=t;
25       inc(i);dec(j);
26     end;
27   until i>j;
28   if i<r then q(i,r);
29   if l<j then q(l,j);
30 end;
31 begin
32   readln(n);
33   for i:=1 to n do read(a[i]);q(1,n);//读入&排序
34   readln(m);
35   for i:=1 to m do
36   begin
37     ans:=0;readln(k);
38     p:=find(1,n+1,k);//找出最小的枚举区间
39     for j:=1 to p do ans:=ans+find(j,p+1,k-a[j])-j;//关键代码,好好理解
40     writeln(ans);
41   end;
42 end.

欢迎转载,请注明出处。

时间: 2024-10-06 13:49:56

CodeVS 1432-总数统计的相关文章

二分法 codevs 1432 总数统计

codevs 1432 总数统计 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 给出n个数,统计两两之和小于k的方案数之和. 输入描述 Input Description 第一行一个数n,表示数字的个数:第二行到第n + 1行,每行一个不超过2,000,000,000的数k:第n + 2行一个数m,表示m个问题:第n + 3行到第n + m + 2行,每行一个数m,询问表示n中两两组合不超过m的组合的个数: 输出描述 O

1432 总数统计

1432 总数统计 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 给出n个数,统计两两之和小于k的方案数之和. 输入描述 Input Description 第一行一个数n,表示数字的个数:第二行到第n + 1行,每行一个不超过2,000,000,000的数k:第n + 2行一个数m,表示m个问题:第n + 3行到第n + m + 2行,每行一个数m,询问表示n中两两组合不超过m的组合的个数: 输出描述 Outpu

[codevs 1482]路线统计(矩阵乘法)

题目:http://codevs.cn/problem/1482/ 分析:很像“经过K条边的最短路径条数”.但有所不同,那就是不是边数固定,而是路径总长度固定.看似不能用矩阵乘法了……但注意到每条边的长度<=5,所以可以把每个点拆成5个,每条边的边权都为1,那么路径总长度固定也就转成了边数固定.然后矩阵乘法秒之(集训队论文2008)

总数统计

[题目描述] 给出n个数,统计两两之和小于k的方案数之和. [输入描述] 第一行一个数n,表示数字的个数: 第二行到第n + 1行,每行一个不超过2,000,000,000的数k: 第n+2行一个数m,表示m个问题: 第n+3行到第n+m+2行,每行一个数m,询问表示n中两两组合不超过m的组合的个数. [输出描述] 输出m行,每行对应一个答案. [样例输入] 3 1 2 3 2 2 3 [样例输出] 0 1 [数据范围及提示] 30%的数据1 ≤ n ≤ 100, 1 ≤ m ≤ 50, k ≤

CodeVS 1296 营业额统计

1296 营业额统计2002年 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证

spark-sql分组去重总数统计uv

SparkConf sparkConf = new SparkConf(); sparkConf .setAppName("Internal_Func") .setMaster("local"); JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf); SQLContext sqlContext = new SQLContext(javaSparkContext); List<S

Java学习(4):统计一个文件中的英文,中文,数字,其他字符以及字符总数

要求:统计一个文件中的英文,中文,数字,其他字符以及字符总数(此随笔以txt文件为例) import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; /** * 将一个文件中英文,中文,数字,其

第二周作业-词频统计

本周作业是词频统计,编程具体要求如下: https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/922 对实现功能进行简要的介绍: 功能一:小文件输入,为表明程序能跑.需要在控制台下输入命令,得到文件中不重复的总单词数.并对单词出现的次数进行排序输出. 功能二:支持命令行输入英文作品的文件名,亲自录入,输出显示不重复单词总数,并对出现频率最高的前10的单词进行输出 功能三:支持命令行输入存储有英文作品文件的目录名,批量统计词频. 功能四:

使用命令行统计代码行数

作为项目管理者,了解项目的整体情况是很重要的,以前是通过Intellij statitic插件统计代码情况的,但现在Android studio2 不能用了,于是只好通过其它方法统计了.可以直接通过Find 功能查找正则表达式 \n 和下面命令行的简单统计,但统计的维度没有插件那么详细,大家谁有更好的统计工具可以评论啊 打开终端,用cd命令 定位到工程所在的目录,然后调用以下命名即可把每个源代码文件行数及总数统计出来: find . "(" -name "*.m"