acwing基础算法

文章目录

  • 基础算法
    • 快速排序
    • 归并排序
    • 整数二分
    • 浮点数二分
    • 高精度加法
    • 高精度减法
    • 高精度乘法
    • 高精度除法
    • 一维前缀和 —— 模板题
    • 二维前缀和 —— 模板题
    • 一维差分 —— 模板题
    • 二维差分 —— 模板题

acwing基础算法_第1张图片

基础算法

快速排序

void quick_sort(int q[], int l, int r)
{
  if(l >= r)return;
  int i = l - 1, j = r + 1, x = q[l + 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(q, j + 1, r);
}

归并排序

void merge_sort(int q[], int l, int r)
{
  if(l >= r)return;
  
  int mid = l + r >> ;
  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])temp[k++] = q[i++];
    else temp[k++] = q[j++];
  }
  while(i <= mid)temp[k++] = q[i++];
  while(j <= r)temp[k++] = q[j++];
  for(int i = l, j = 0; i <= r; i++, j ++ )q[i] = temp[j];
}

整数二分

bool check(int x){/*...*/}//检查x是否满足某种性质

// 区间[l , r]被划分[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
  while(l < r)
  {
    int mid = l + r >> 1;
    if(check(mid))r = mid;
    else l = mid + 1;
  }
  return l;
}
// 区间[l, r]被划分[l, mid - 1]和[mid, r]使用:
int bsearch_2(int l, int r)
{
  while(l < r)
  {
    int mid = l + r + 1 >> 1;
    if(check(mid)) l = mid;
    else r = mid - 1;
  }
  return l;
}

浮点数二分

bool check(double x) {/*...*/} // 检查x是否满足某种性质

double brearch_3(double l, double r)
{
  const double eps = 1e-6; // eps表示精度, 取决于题目对精度的要求
  while(r - l > eps)
  {
    double mid = (l + r) / 2;
    if(check(mid))r = mid;
    else l = mid;
  }
  return l;
}

高精度加法

// C = A + B, A >= 0, B >= 0;
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);
  while(C.size() > 1&& C.back() == 0)C.pop_back();
  return C;
}

高精度减法

vector<int>cmp(vector<int>&A, vector<int>&B)//将其A < B时进行操作;
{
    if(A.size() != B.size())
    {
      return A.szie() > B.size();
    }
    for(int i = A.size() - 1; i > = 0; i--)
    {
      if(A[i] != B[i])return A[i] > B[i];
    }
}
vector<int>sub(vector<int>&A, vector<int> &B)
{
  vector<int>C;
  int t = 0;
  for(int i = 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;
  cin >> a >> b;
  vector<int>A,B,C;
  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');
  if(cmp(A,B))
  {
    C = sub(A, B);
  }
  else {
    cout << "-" ;
    C = sub(B, A);
  }
  for(int i = C.size() - 1; i >= 0; i--) cout << C[i] ;
  return 0;
} 

高精度乘法

#include 
using namespace std;
#include 

vector<int> mul(vector<int> &A, int b) {
    vector<int> C;
    int t = 0;
    for(int i = 0; i < A.size()|| t; i++) {
        if(i < A.size()) t+= A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }
    return C;
}
int main() {
    string a;
    int b;
    cin >> a >> b;
    vector <int> A;
    for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
    auto C = mul(A, b);
    for(int i = C.size() - 1; i >= 0; i--) cout << C[i];
    return 0;
}

高精度除法

#include 
using namespace std;
#include 
#include 
vector<int>div(vector<int>&A, int b, int &r) {
    vector<int>C;
    r = 0;
    for(int i = A.size() - 1; i >= 0; i--) {
        r = r * 10 + A[i];
        C.push_back(r / b);
        r %= b;
    }
    reverse(C.begin(), C.end());
    while(C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}
int main() {
    string a;
    int r = 0;
    int b;
    cin >> a >> b;
    vector<int>A;
    for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
    auto C = div(A, b, r);
    for(int i = C.size() - 1; i >= 0; i--) {
        cout << C[i];
    }
    cout << endl;
    cout << r << endl;
    return 0;
}

一维前缀和 —— 模板题

S[i] = a[1] + a[2] + ... a[i]
a[l] + ... + a[r] = S[r] - S[l - 1]

  • 前缀和

输入一个长度为n的整数序列。

接下来再输入m个询问,每个询问输入一对l, r。

对于每个询问,输出原序列中从第l个数到第r个数的和。

输入格式

第一行包含两个整数n和m。

第二行包含n个整数,表示整数数列。

接下来m行,每行包含两个整数l和r,表示一个询问的区间范围。

输出格式

共m行,每行输出一个询问的结果。

数据范围

1≤l≤r≤n1≤l≤r≤n,
1≤n,m≤1000001≤n,m≤100000,
−1000≤数列中元素的值≤1000−1000≤数列中元素的值≤1000

输入样例:

5 3
2 1 3 6 4
1 2
1 3
2 4


输出样例:

3
6
10

#include
using namespace std;
const int N = 15000000;
int q[N];
int main()
{
    int n, m;
    cin >> n >> m;
    int w;
    for(int i = 1; i <= n; i++)
    {
        cin >> w;
        q[i] = q[i - 1] + w;
    }
    while(m--)
    {
        int l , r;
        cin >> l >> r;
    cout << q[r] - q[l - 1] <<endl;
    }
    return 0;
}

二维前缀和 —— 模板题

S[i, j] = 第i行j列格子左上部分所有元素的和
以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]

  • **子矩阵的和 **

输入一个n行m列的整数矩阵,再输入q个询问,每个询问包含四个整数x1, y1, x2, y2,表示一个子矩阵的左上角坐标和右下角坐标。

对于每个询问输出子矩阵中所有数的和。

输入格式

第一行包含三个整数n,m,q。

接下来n行,每行包含m个整数,表示整数矩阵。

接下来q行,每行包含四个整数x1, y1, x2, y2,表示一组询问。

输出格式

共q行,每行输出一个询问的结果。

数据范围

1≤n,m≤10001≤n,m≤1000,
1≤q≤2000001≤q≤200000,
1≤x1≤x2≤n1≤x1≤x2≤n,
1≤y1≤y2≤m1≤y1≤y2≤m,
−1000≤矩阵内元素的值≤1000−1000≤矩阵内元素的值≤1000

输入样例:

3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4


输出样例:

17
27
21

#include
using namespace std;
int n, m , p;
const int N = 1050;
int a[N][N], s[N][N];
int main()
{
    cin >> n >> m >> p;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            cin >> a[i][j];
        }
    }
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            s[i][j] = s[i][ j - 1] + s[i - 1][j] - s[i - 1][j - 1] + a[i][j];
        } 
    }
    int x1, y1, x2, y2;
    while(p--){
       cin >> x1 >> y1 >> x2 >> y2;
       cout << s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1] << endl;
    }
    
    return 0;
}

一维差分 —— 模板题

给区间[l, r]中的每个数加上c:B[l] += c, B[r + 1] -= c

  • 差分

输入一个长度为n的整数序列。

接下来输入m个操作,每个操作包含三个整数l, r, c,表示将序列中[l, r]之间的每个数加上c。

请你输出进行完所有操作后的序列。

输入格式

第一行包含两个整数n和m。

第二行包含n个整数,表示整数序列。

接下来m行,每行包含三个整数l,r,c,表示一个操作。

输出格式

共一行,包含n个整数,表示最终序列。

数据范围

1≤n,m≤1000001≤n,m≤100000,
1≤l≤r≤n1≤l≤r≤n,
−1000≤c≤1000−1000≤c≤1000,
−1000≤整数序列中元素的值≤1000−1000≤整数序列中元素的值≤1000

输入样例:

6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1



输出样例:

3 4 5 3 4 2

#include
using namespace std;
const int N = 1000005;
int a[N], b[N];
void insert(int l, int r, int c)
{
    b[l] += c;
    b[r + 1] -= c;
}
int main()
{
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for(int i = 1; i <= n; i++)
    {
        insert(i , i , a[i]);
    }
    int l, r, c;
    while(m --)
    {
        cin >> l >> r >> c;
        insert(l , r, c);
    }
    for(int i = 1; i <= n; i++){
        a[i] = a[i - 1] + b[i];
    }
    for(int i = 1; i <= n; i++)
    {
        cout << a[i]<<' ';
    }
 return 0;   
}

二维差分 —— 模板题

给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c

  • 差分矩阵

你可能感兴趣的:(算法)