#  AcWing 785. 快速排序 
#  题目描述 
给定你一个长度为 n 的整数数列。
请你使用快速排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。
#  输入格式 
输入共两行,第一行包含整数 n。
第二行包含 n 个整数(所有整数均在 1∼109 范围内),表示整个数列。
#  输出格式 
输出共一行,包含 n 个整数,表示排好序的数列。
#  数据范围 
1≤n≤100000
#  输入样例: 
 
#  输出样例: 
 
#  解题思路 
#  题意理解 
这道题目显然是要我们将一个无序数列排序,成为具有升序性质的升序序列.
#  算法处理 
一道排序题目,数据范围是关键,我们发现这道题目只能让我们使用 O (nlogn) 的算法,显然我们可以选择快速排序,归并排序等算法,这里我们就使用快速排序.
#  代码实现 
#  C++ 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <iostream>  using  namespace  std;const  int  N = 1e6  + 10 ;int  n;int  q[N];void  quick_sort (int  q[],int  l,int  r)   {         if (l >= r) return ;           int  x = q[(l + r) / 2 ],i = l - 1 , j = r + 1 ;                while (i < j) {          do  i++; while (q[i] < x);          do  j--; while (q[j] > x);          if (i < j) swap (q[i],q[j]);               }               quick_sort (q, l, j);      quick_sort (q, j + 1 , r); } int  main ()   {         scanf ("%d" ,&n);     for (int  i = 0 ; i < n ; i++) scanf ("%d" ,&q[i]);          quick_sort (q, 0  ,n-1 );          for (int  i = 0 ; i < n ; i++) printf ("%d " ,q[i]);          return  0 ; } 
 
#  Java 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 package  基础算法;import  java.util.Scanner;public  class  Quick_Sort   {     public  static  int  N = (int ) (1e6  +10 );     public  static  int  n;      public  static  int  [] p = new  int [N];     public  static  void  quick_sort (int [] p,int  l,int  r)   {         if (l >= r) return ;          int  x = p[(l + r)/2 ],i = l - 1 ,j = r + 1 ;                  while (i < j) {              do  i++; while (p[i] < x);              do  j--; while (p[j] > x);              if (i < j) {                  int  t = p[i];                 p[i] = p[j];                 p[j] = t;             }         }         quick_sort(p,l,j);          quick_sort(p,j+1 ,r);      }     public  static  void  main (String[] args)   {         Scanner in = new  Scanner(System.in);         n = in.nextInt();         for  (int  i = 0 ;i < n;i++) {             p[i] = in.nextInt();         }         quick_sort(p,0 ,n-1 );          for  (int  i = 0 ;i < n;i++) {             System.out.println(p[i]);         }     } } 
 
#  AcWing 787. 归并排序 
#  题目描述 
给定你一个长度为 n 的整数数列。
请你使用归并排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。
#  输入格式 
输入共两行,第一行包含整数 n。
第二行包含 n 个整数(所有整数均在 1∼109 范围内),表示整个数列。
#  输出格式 
输出共一行,包含 n 个整数,表示排好序的数列。
#  数据范围 
1≤n≤100000
#  输入样例: 
 
#  输出样例: 
 
#  解题思路 
#  题意理解 
这道题目还是让我们排序,只不过这里强制要求我们使用归并排序,所以既然如此的话,让我们好好地康康这道题目.
#  算法处理 
归并排序,它有两大核心操作.
一个是将数组一分为二,一个无序的数组成为两个数组.
另外一个操作就是,合二为一,将两个有序数组合并成为一个有序数组.
#  代码实现 
#  C++ 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #include <iostream>  using  namespace  std;const  int  N = 1e6  + 10 ;int  n; int  q[N],tmp[N]; void  merge_sort (int  q[],int  l,int  r)   {     if (l >= r) return ;          int  mid = (l + r) >> 1 ;           merge_sort (q,l,mid);      merge_sort (q,mid+1 ,r);           int  k = 0 ,i = l,j = mid+1 ;      while (i <= mid && j <= r)          if (q[i] <= q[j]) tmp[k++] = q[i++];          else  tmp[k++] = q[j++];                while (i <= mid) tmp[k++] = q[i++];      while (j <= r) tmp[k++] = q[j++];           for (i = l,j = 0 ;i <= r;i++,j++) q[i] = tmp[j];       } int  main ()   {         scanf ("%d" ,&n);     for (int  i = 0 ;i < n;i++) scanf ("%d" ,&q[i]);          merge_sort (q,0 ,n-1 );          for (int  i = 0 ;i < n;i++) printf ("%d " ,q[i]);          return  0 ; } 
 
#  Java 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 package  基础算法;import  java.util.Scanner;public  class  Merge_Sort   {    public  static  int  N = (int ) (1e6  +10 );     public  static  int  n;      public  static  int  [] p = new  int [N];     public  static  int  [] tmp = new  int [N];     public  static  void  merge_sort (int [] p,int  l,int  r)   {         if (l >= r) return ;         int  mid = (l + r) >> 1 ;          merge_sort(p,l,mid);          merge_sort(p,mid+1 ,r);          int  k = 0 ,i = l,j = mid+1 ;          while (i <= mid && j <= r)              if (p[i] <= p[j]) tmp[k++] = p[i++];              else  tmp[k++] = p[j++];                   while (i <= mid) tmp[k++] = p[i++];          while (j <= r) tmp[k++] = p[j++];          for (i = l,j = 0 ;i <= r;i++,j++) p[i] = tmp[j];      }     public  static  void  main (String[] args)   {         Scanner in = new  Scanner(System.in);         n = in.nextInt();         for  (int  i = 0 ;i < n;i++) {             p[i] = in.nextInt();         }         merge_sort(p,0 ,n-1 );          for  (int  i = 0 ;i < n;i++) {             System.out.println(p[i]);         }     } } 
 
#  AcWing 789. 数的范围(二分) 
#  题目描述 
给定一个按照升序排列的长度为 n 的整数数组,以及 q 个查询。
对于每个查询,返回一个元素 k 的起始位置和终止位置(位置从 00 开始计数)。
如果数组中不存在该元素,则返回  -1 -1 。
#  输入格式 
第一行包含整数 n 和 q,表示数组长度和询问个数。
第二行包含 n 个整数(均在 1∼10000 范围内),表示完整数组。
接下来 q 行,每行包含一个整数 k,表示一个询问元素。
#  输出格式 
共 q 行,每行包含两个整数,表示所求元素的起始位置和终止位置。
如果数组中不存在该元素,则返回  -1 -1 。
#  数据范围 
1≤n≤100000 
1≤q≤10000 
1≤k≤10000
#  输入样例: 
 
#  输出样例: 
 
#  解题思路 
#  整数二分 
二分的本质是二段性不是单调性。
当想找不满足性质的边界值(红色区域的右边界值)
找中间值  mid = (l+r+1)/2  
if (check (mid)) 等于 true 或者是 false 
check (m) 是检查 m 是在不满足性质的区间 (检查是不是在红色区间) 
更新 l 或者 r
当想找满足性质的边界值(绿色区域的左边界值)
找中间值  mid = (l+r)/2 
if (check (mid)) 等于 true 或者是 false 
check (m) 是检查 m 是在满足性质的区间 (检查是不是在绿色区间) 
更新 l 或者 r 
 
归结上面的两种二分方法,步骤为:
先写一个 check 函数 
判定在 check 的情况下(true 和 false 的情况下),如何更新区间。 
在 check (m)==true 的分支下是:
l=mid  的情况,中间点的更新方式是 m=(l+r+1)/2 
r=mid  的情况,中间点的更新方式是 m=(l+r)/2 
 
 
 
这种方法保证了:
最后的 l==r 
搜索到达的答案是闭区间的,即 a [l] 是满足 check () 条件的。 
 
#  代码实现 
#  Java 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import  java.util.Scanner;public  class  Main   {         public  static  int  N = (int )1e5 +10 ;     public  static  int  n,m;     public  static  int [] q = new  int [N];          public  static  void  main (String[] srgs)   {         Scanner in = new  Scanner(System.in);         n = in.nextInt();          m = in.nextInt();          for (int  i = 0 ;i <n;i++) q[i] = in.nextInt();          while (m-- > 0 ) {              int  x;             x = in.nextInt();              int  l = 0 , r = n - 1 ;              while  (l < r) {                  int  mid = l + r >> 1 ;                  if  (q[mid] >= x) r = mid;                  else  l = mid + 1 ;              }             if  (q[l] != x) System.out.println("-1 -1" );              else  {                 System.out.print(l + " " );                  l = 0 ;r = n - 1 ;                  while  (l < r) {                      int  mid = l + r + 1  >> 1 ;                      if  (q[mid] <= x) l = mid;                      else  r = mid - 1 ;                  }                 System.out.println(l);              }         }                       }      } 
 
#  C++ 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include <iostream>  using  namespace  std;int  n,m;const  int  N = 1e6 +10 ;int  q[N];int  main ()   {         scanf ("%d%d" ,&n,&m);     for (int  i = 0 ;i < n;i++)          scanf ("%d" ,&q[i]);          while (m--) {          int  x = 0 ;         scanf ("%d" ,&x);                   int  l = 0 ,r = n-1 ;                            while (l < r) {              int  mid = (l + r) >> 1 ;              if (q[mid] >= x) r = mid;              else  l = mid+1 ;          }         if (q[l] != x) cout << "-1 -1"  << endl;          else  {             cout << l << " "  ;              l = 0 ,r = n-1 ;                                        while (l < r) {                  int  mid = (l + r + 1 ) >> 1 ;                  if (q[mid] <= x) l = mid;                  else  r = mid-1 ;              }             cout << l << endl;                       }              }          return  0 ; } 
 
#  AcWing 790. 数的三次方根(二分) 
#  题目描述 
给定一个浮点数 n,求它的三次方根。
#  输入格式 
共一行,包含一个浮点数 n。
#  输出格式 
共一行,包含一个浮点数,表示问题的解。
注意,结果保留 6 位小数。
#  数据范围 
−10000≤n≤10000
#  输入样例: 
 
#  输出样例: 
 
#  解题思路 
学会整数二分后,相信这个大家有手就行。
#  代码实现 
#  C++ 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include  <iostream>  using  namespace  std;double  x;int  main ()   {    cin >> x;      double  l = -10000 ,r = 10000 ;           while (r - l > 1e-8 ) {          double  mid = (l + r) / 2 ;          if (mid*mid*mid >= x) r = mid;         else  l = mid;     }     printf ("%lf\n" ,l);           return  0 ; } 
 
#  Java 
JAVA 字符串格式化 ——String.format () 的使用 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import  java.util.Scanner;public  class  Main   {    public  static  void  main (String[] srgs)   {         Scanner in = new  Scanner(System.in);         double  x;         x = in.nextDouble();          double  l = -10000 ,r = 10000 ;          while (r - l > 1e-8 ) {              double  mid = (l + r) / 2 ;              if (mid*mid*mid >= x) r = mid;             else  l = mid;         }         System.out.println(String.format("%.6f" , l));               }      } 
 
#  AcWing 791. 高精度加法 
#  题目描述 
给定两个正整数(不含前导 00),计算它们的和。
#  输入格式 
共两行,每行包含一个整数。
#  输出格式 
共一行,包含所求的和。
#  数据范围 
1≤整数长度≤1000001≤整数长度≤100000
#  输入样例: 
 
#  输出样例: 
 
#  解题思路 
因为是长整数的加法运算,普通的数据类型无法存放,所以选择了 vector(也因为有  .size  这个函数才采用它)。
 
过长的数据使我选择了字符串来读入,用循环放入 vector 即可(将数字低位在前高位在后的放入)。
 
在循环中通过算子 t  来进行每一位的运算,并将下一次运算的进位算出: t /= 10; (参与下一位数的运算),剩余部分写入结果中: C.push_back(t%10); 。
 
循环结束(各位的运算完成)后,如果最高位时 0,则需要进一位: C.push_back(1);
 
 
#  代码实现 
#  C++ 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include  <iostream>  #include  <vector>  using  namespace  std;vector<int > add (vector<int > &A,vector<int > &B)   {          vector<int > C;           int  t = 0 ;      for (int  i = 0 ;i < A.size () || i < B.size ();i++) {          if (i < A.size ()) t += A[i];          if (i < B.size ()) t += B[i];          C.push_back (t%10 );          t /= 10 ;      }     if (t) C.push_back (1 );      return  C; } int  main ()   {    string a,b;     vector<int > A,B;          cin >> a >> b;                for (int  i = a.size () - 1 ;i >= 0 ;i--) A.push_back (a[i] - '0' );      for (int  i = b.size () - 1 ;i >= 0 ;i--) B.push_back (b[i] - '0' );           vector<int > C = add (A,B);                for (int  i = C.size () - 1 ;i >= 0 ;i--) printf ("%d" ,C[i]);           return  0 ; } 
 
#  AcWing 792. 高精度减法 
#  题目描述 
给定两个正整数(不含前导 0),计算它们的差,计算结果可能为负数。
#  输入格式 
共两行,每行包含一个整数。
#  输出格式 
共一行,包含所求的差。
#  数据范围 
1≤整数长度≤105
#  输入样例: 
 
#  输出样例: 
 
#  解题思路 
判断需要相减的两个数的大小,然后进行逐位相减。
#  代码实现 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include  <iostream>  #include  <vector>  using  namespace  std;bool  cmp (vector<int > &A, vector<int > &B)  {    if  (A.size () != B.size ()) return  A.size () > B.size ();      for  (int  i = A.size () - 1 ; i >= 0 ; i -- )          if  (A[i] != B[i])             return  A[i] > B[i];     return  true ;  } vector<int > sub (vector<int > &A, vector<int > &B)   {    vector<int > C;          for  (int  i = 0 , t = 0 ; i < A.size (); i ++ )     {         t = A[i] - t;          if  (i < B.size ()) t -= B[i];          C.push_back ((t + 10 ) % 10 );                            if  (t < 0 ) t = 1 ;         else  t = 0 ;     }     while  (C.size () > 1  && C.back () == 0 ) C.pop_back ();      return  C; } int  main ()  {    string a, b;     vector<int > A, B;     cin >> a >> b;      for  (int  i = a.size () - 1 ; i >= 0 ; i -- ) A.push_back (a[i] - '0' );      for  (int  i = b.size () - 1 ; i >= 0 ; i -- ) B.push_back (b[i] - '0' );      vector<int > C;           if  (cmp (A, B)) C = sub (A, B);     else  C = sub (B, A), cout << '-' ;          for  (int  i = C.size () - 1 ; i >= 0 ; i -- ) cout << C[i];     cout << endl;     return  0 ; } 
 
#  写在后面 
暂时先写这么多,学了其他的继续写(~~ 菜鸡嘤嘤