(1)P2249 【深基13.例1】查找
这道题本身并不难,典型的一个二分查找,用java自带的二分查找函数就可以实现.但是这题存在多个值相同的情况,根据例题我们知道,返回的是第一个数字。但如果直接用二分搜索肯定不能保障搜索到的是第一个,那么 我们就要自己手写一个二分查找,并且当找到了元素后再判断一下是不是第一个,如果不是我们就往前移。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
String[] s=br.readLine().split(" ");
int n=Integer.valueOf(s[0]),m=Integer.valueOf(s[1]);
int[] arr=new int[n+1];
s=br.readLine().split(" ");
for(int i=1;i<=n;i++) {
arr[i]=Integer.valueOf(s[i-1]);
}
s=br.readLine().split(" ");
for(int i=0;i<m;i++) {
out.print(binarySearch(1, n, arr, Integer.valueOf(s[i]))+" ");
}
out.close();
}
static int binarySearch(int l,int r,int[] arr,int k) {
int res=-1;
while(l<=r) {
int m=(l+r)/2;
if(arr[m]==k) {
res=m;
break;
}
else if(arr[m]>k) {
r=m-1;
}
else if(arr[m]<k) {
l=m+1;
}
}
if(res!=-1) {
while(arr[res-1]==k&&res!=1) {
res--;
}
}
return res;
}
}
(2)P1102 A-B 数对
这道题有一个非常巧妙的方法,利用Map集合,首先遍历一遍数组,将各个数字和它出现的次数用map存储起来。然后将数组中每个元素减c。最后再遍历一遍数组,把数字中每个元素出现的次数累加起来。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String[] s=br.readLine().split(" ");
int n=Integer.valueOf(s[0]),m=Integer.valueOf(s[1]);
HashMap<Integer, Integer> hs=new HashMap<Integer, Integer>();
int[] arr=new int[n];
s=br.readLine().split(" ");
for(int i=0;i<n;i++) {
arr[i]=Integer.valueOf(s[i]);
if(hs.containsKey(arr[i])) {
hs.put(arr[i], hs.get(arr[i])+1);
}
else {
hs.put(arr[i], 1);
}
arr[i]-=m;
}
long sum=0;
for(int i=0;i<n;i++) {
if(hs.containsKey(arr[i]))
sum+=hs.get(arr[i]);
}
System.out.println(sum);
}
}
(3)P1873 砍树
一道二分答案题目,像这种题目一般都是有一个模板的。用二分来选取一个砍树的高度,然后写个函数判断这个长度是否满足条件,如果满足,则在更高的长度进行选取,不满足则在低的长度选取。
ps:这题有一个点用java做会超内存。。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int[] arr;
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String[] s=br.readLine().split(" ");
int n=Integer.valueOf(s[0]),m=Integer.valueOf(s[1]);
arr=new int[n];
s=br.readLine().split(" ");
for(int i=0;i<n;i++) {
arr[i]=Integer.valueOf(s[i]);
}
int l=1,r=1000000000;
int max=0;
while(l<=r) {
int mid=(l+r)/2;
if(judge(mid,m)) {
max=mid;
l=mid+1;
}
else {
r=mid-1;
}
}
System.out.println(max);
}
public static boolean judge(int mid,int k) {
int sum=0;
for(int i=0;i<arr.length;i++) {
if(arr[i]>mid) {
sum+=arr[i]-mid;
}
if(sum>=k) {
return true;
}
}
return false;
}
}
(4)P1024 一元三次方程求解
首先,解的范围是-100到100,而且每个解绝对值差大于1,那么可以枚举每个区间,每个区间的大小为1。然后把区间端点带入方程,如果左端点为0,直接输出左端点。否则用二分的思想,在区间内寻找解,因为要满足f(x1)*f(x2)<0才可能有解
import java.util.Scanner;
public class Main {
static double a,b,c,d;
public static double f(double x) {
return a*x*x*x+b*x*x+c*x+d;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
a=sc.nextDouble();b=sc.nextDouble();c=sc.nextDouble();d=sc.nextDouble();
double l,r;
for(int i=-100;i<100;i++) {
l=i;r=i+1;
double f1=f(l);
double f2=f(r);
if(f1==0)
{
System.out.print(String.format("%.2f", l)+" ");
}
if(f1*f2<0) {
while(r-l>=0.001) {
double m=(l+r)/2;
if(f(m)*f(r)<=0)
l=m;
else
r=m;
}
System.out.print(String.format("%.2f", r)+" ");
}
}
}
}