P1102 A-B 数对
题目背景
出题是一件痛苦的事情!
相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!
## 题目描述
给出一串正整数数列以及一个正整数 $C$,要求计算出所有满足 $A - B = C$ 的数对的个数(不同位置的数字一样的数对算不同的数对)。
## 输入格式
输入共两行。
第一行,两个正整数 $N,C$。
第二行,$N$ 个正整数,作为要求处理的那串数。
## 输出格式
一行,表示该串正整数中包含的满足 $A - B = C$ 的数对的个数。
## 输入输出样例 #1
### 输入 #1
```
4 1
1 1 2 3
```### 输出 #1
```
3
```## 说明/提示
对于 $75\%$ 的数据,$1 \leq N \leq 2000$。
对于 $100\%$ 的数据,$1 \leq N \leq 2 \times 10^5$,$0 \leq a_i <2^{30}$,$1 \leq C < 2^{30}$。
2017/4/29 新添数据两组
先想暴力搜索
import java.util.Scanner;
import java.util.Arrays;
public class Main {
private static int[] nums;
private static int sum;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int C = scan.nextInt();
nums = new int[N];
for (int i = 0; i < N; i++) {
nums[i] = scan.nextInt();
}
Arrays.sort(nums);
for (int i = nums.length - 1; i >= 0; i--) {
for (int j = i - 1; j >= 0; j--) {
if(nums[i] - nums[j] == C)
sum ++;
}
}
System.out.println(sum);
}
}
一边使用二分
import java.util.Scanner;
import java.util.Arrays;
public class Main {
private static int[] nums;
private static int C;
private static int sum;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int C = scan.nextInt();
nums = new int[N + 1];
for (int i = 1; i <= N; i++) {
nums[i] = scan.nextInt();
}
Arrays.sort(nums);
for (int i = nums.length - 1; i >= 0; i--) {
binarySearch(0,i + 1,nums[i] - C);
}
System.out.println(sum);
}
private static void binarySearch(int left,int right,int tar) {
if(tar < nums[1] || tar > nums[nums.length - 1])
return;
int rigB = right;
int mid = 0;
while(left + 1 < right) {
mid = (left + right) / 2;
if(isBlue(mid,tar))
left = mid;
else
right = mid;
}
if(nums[right] != tar)
return;
for (int i = right; i < rigB; i++) {
if(nums[i] == tar)
sum ++;
}
}
private static boolean isBlue(int x,int tar) {
return nums[x] < tar;
}
}
两边使用二分但是没有开long
import java.util.Scanner;
import java.util.Arrays;
public class Main {
private static int[] nums;
private static int C;
private static int sum;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int C = scan.nextInt();
nums = new int[N + 1];
for (int i = 1; i <= N; i++) {
nums[i] = scan.nextInt();
}
Arrays.sort(nums);
for (int i = nums.length - 1; i >= 0; i--) {
int leftB = binarySearch(0, i + 1, nums[i] - C);
if (leftB == -1)
continue;
int rigB = binarySearch02(0,i + 1,nums[i] - C);
sum += rigB - leftB + 1;
}
System.out.println(sum);
}
private static int binarySearch(int left, int right, int tar) {
if (tar < nums[1] || tar > nums[nums.length - 1])
return -1;
int rigB = right;
int mid = 0;
while (left + 1 < right) {
mid = (left + right) / 2;
if (isBlue(mid, tar))
left = mid;
else
right = mid;
}
if (nums[right] == tar)
return right;
return -1;
}
private static int binarySearch02(int left, int right, int tar) {
int mid = 0;
while (left + 1 < right) {
mid = (left + right) / 2;
if (isRed(mid, tar))
right = mid;
else
left = mid;
}
if(nums[left] == tar)
return left;
return -1;
}
private static boolean isBlue(int x, int tar) {
return nums[x] < tar;
}
private static boolean isRed(int x, int tar) {
return nums[x] > tar;
}
}
开了long之后过了
import java.util.Scanner;
import java.util.Arrays;
public class Main {
private static int[] nums;
private static int C;
private static long sum;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int C = scan.nextInt();
nums = new int[N + 1];
for (int i = 1; i <= N; i++) {
nums[i] = scan.nextInt();
}
Arrays.sort(nums);
for (int i = nums.length - 1; i >= 0; i--) {
int leftB = binarySearch(0, i + 1, nums[i] - C);
if (leftB == -1)
continue;
int rigB = binarySearch02(0,i + 1,nums[i] - C);
sum += rigB - leftB + 1;
}
System.out.println(sum);
}
private static int binarySearch(int left, int right, int tar) {
if (tar < nums[1] || tar > nums[nums.length - 1])
return -1;
int rigB = right;
int mid = 0;
while (left + 1 < right) {
mid = (left + right) / 2;
if (isBlue(mid, tar))
left = mid;
else
right = mid;
}
if (nums[right] == tar)
return right;
return -1;
}
private static int binarySearch02(int left, int right, int tar) {
int mid = 0;
while (left + 1 < right) {
mid = (left + right) / 2;
if (isRed(mid, tar))
right = mid;
else
left = mid;
}
if(nums[left] == tar)
return left;
return -1;
}
private static boolean isBlue(int x, int tar) {
return nums[x] < tar;
}
private static boolean isRed(int x, int tar) {
return nums[x] > tar;
}
}
二分用不用还是依据时间复杂度来看的!
会二分发现那里不够用,可以用二分。把那个问题转化为二分问题
甚至可以进一步分析
找好的老师,这次找了——会code的小金鱼——几乎是马上就学会了二分!!!!!!!!!!
二分查找 | 妈妈再也不怕我写错二分啦 | 五点七边二分视频补充_哔哩哔哩_bilibili
二分查找为什么总是写错?_哔哩哔哩_bilibili
二分习题课 | 手把手教你二分答案! | 超级细不听血亏_哔哩哔哩_bilibili