算法基础模板整理(基础知识篇)
排序
快速排序 线性时间选择
int partition(int l, int r){
int pos = rand() % (r - l + 1) + l;
swap(a[pos], a[l]);
int key = a[l], i = l, j = r;
while(i != j){
while(i < j && a[j] >= key) j -- ;
while(i < j && a[i] <= key) i ++ ;
swap(a[i], a[j]);
}
swap(a[i], a[l]);
return i;
}
int select(int l, int r, int k){
if(l == r) return a[l];
int mid = partition(l, r);
int res = mid - l + 1; //res表示当前是范围内的第几小
if(k == res) return a[mid];
if(k < res) return select(l, mid - 1, k);
else return select(mid + 1, r, k - res);
}
归并排序 归并排序求逆序对
void merge(int l, int mid, int r){
int tmp[r - l + 1];
int i = l, j = mid + 1, k = 0;
while(i <= mid && j <= r){
if(a[i] <= a[j]) tmp[k ++ ] = a[i ++ ];
else tmp[k ++ ] = a[j ++ ], res += mid - i + 1;
}
while(i <= mid) tmp[k ++ ] = a[i ++ ];
while(j <= r) tmp[k ++ ] = a[j ++ ];
for(int idx = l, kk = 0; idx <= r; idx ++ , kk ++ )
a[idx] = tmp[kk];
}
void mergesort(int l, int r){
if(l >= r) return;
int mid = l + r >> 1;
mergesort(l, mid);
mergesort(mid + 1, r);
merge(l, mid, r);
}
二分查找
int binaryfirst(int a[], int x){
int l = 0, r = n - 1;
while(l < r){
int mid = l + r >> 1;
if(a[mid] >= x) r = mid;
else l = mid + 1;
}
return a[r] == x ? r : -1;
}
int binarylast(int a[], int x){
int l = 0, r = n - 1;
while(l < r){
int mid = l + r + 1 >> 1;
if(a[mid] <= x) l = mid;
else r = mid - 1;
}
return a[r] == x ? r : -1;
}
高精度
高精度加法
vector<int> add(vector<int> &A, vector<int> &B){
vector<int> C;
int m = A.size(), n = B.size();
int cur = 0, i = 0;
while(i < m || i < n){
if(i < m) cur += A[i];
if(i < n) cur += B[i];
C.push_back(cur % 10);
cur /= 10;
i ++ ;
}
if(cur) C.push_back(1);
return C;
}
int main(){
string a, b; cin >> a >> b;
vector<int> 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 -- ) cout << C[i];
return 0;
}
高精度减法
bool cmp(vector<int>& A, vector<int> &B){
if(A.size() != B.size()) return A.size() > B.size();
for(int i = A.size(); 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;
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(); //去掉前导0
return C;
}
int main(){
string a, b; cin >> a >> b;
vector<int> 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');
if(cmp(A, B)){
auto C = sub(A, B);
for(int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
}else{
auto C = sub(B, A);
printf("-");
for(int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
}
return 0;
}
高精度乘法
vector<int> mul(vector <int> & A, int b) {
vector<int> C;
int t = 0;
for(int i = 0; i < A.size(); i ++ ){
t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
while(t){
C.push_back(t % 10);
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
高精度除法
vector<int> div(vector<int> &A, int b, int &r){
vector<int> C;
for(int i = 0; i < A.size(); i ++ ){
r = r * 10 + A[i];
C.push_back(r / b);
r = r % b;
}
reverse(C.begin(), C.end());
while(C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
前缀和
一维前缀和
static const int N = 1e5 + 10;
int a[N], s[N], n, q;
int main(){
cin >> n >> q;
for(int i = 1; i <= n; i ++ ){
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
while(q -- ){
int l, r; cin >> l >> r;
cout << s[r] - s[l - 1] << endl;
}
return 0;
}
二维前缀和
static const int N = 1010;
int s[N][N], n, m, q;
int main(){
cin >> n >> m >> q;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++){
int x; cin >> x;
s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + x;
}
while(q -- ){
int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
cout << s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1] << endl;
}
return 0;
}
差分
一维差分
static const int N = 1e5 + 10;
int b[N];
int main(){
int n, m; cin >> n >> m;
for(int i = 1; i <= n; i ++ ){
int x; cin >> x;
b[i] += x, b[i + 1] -= x;
}
while(m -- ){
int l, r, c; cin >> l >> r >> c;
b[l] += c, b[r + 1] -= c;
}
for(int i = 1; i <= n; i ++ )
b[i] += b[i - 1], cout << b[i] << ' ';
}
二维差分
static const int N = 1010;
int b[N][N];
void insert(int x1, int y1, int x2, int y2, int c){
b[x1][y1] += c;
b[x1][y2 + 1] -= c;
b[x2 + 1][y1] -= c;
b[x2 + 1][y2 + 1] += c;
}
int main(){
int n, m, q; cin >> n >> m >> q;
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ ){
int c; cin >> c;
insert(i, j, i, j, c);
}
while(q -- ){
int x1, y1, x2, y2, c; cin >> x1 >> y1 >> x2 >> y2 >> c;
insert(x1, y1, x2, y2, c);
}
for(int i = 1; i <= n; i ++ ){
for(int j = 1; j <= m; j ++ ){
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
cout << b[i][j] << ' ';
}
cout << endl;
}
}
倍增
RMQ 区间最值问题
void rmq(){
for(int i = 1; i <= n; i ++ ) dp[i][0] = a[i];
for(int j = 1; j < int(log(n) / log(2)) + 1; j ++ )
for(int i = 1; i <= n - (1 << j) + 1; i ++ )
dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
//分为 [i, i + 2^(j - 1) - 1] 和 [i + 2^(j - 1), i + 2^j - 1] 两个区间的最值的最值
}
while(m -- ){
int l, r; cin >> l >> r;
int k = log(r - l + 1) / log(2);
cout << max(dp[l][k], dp[r - (1 << k) + 1][k]) << endl;
//以l为开头 [l, l + 2^k - 1] , 以r为结尾 [r - 2^k + 1, r]
}
区间合并
static const int N = 1e5 + 10;
typedef pair<int, int> pii;
#define l first
#define r second
pii in[N], res[N];
int cnt, n;
int main(){
cin >> n;
for(int i = 1; i <= n; i ++ ) cin >> in[i].l >> in[i].r;
sort(in + 1, in + n + 1);
for(int i = 1; i <= n; i ++ )
if(cnt == 0 || res[cnt].r < in[i].l) res[ ++ cnt] = in[i];
else res[cnt].r = max(res[cnt].r, in[i].r);
cout << cnt;
return 0;
}
离散化
sort(alls.begin(), alls.end()); //排序
alls.erase(unique(alls.begin(), alls.end()), alls.end()); //去重
for(auto num : v){
int x = lower_bound(alls.begin(), alls.end(), num) - alls.begin();
//二分查找找到x的映射值
...
}
一切都是命运石之门的选择,本文章来源于博客园,作者:MarisaMagic,出处:https://www.cnblogs.com/MarisaMagic/p/17317060.html,未经允许严禁转载