我真的不想再摆|

Go1NgZCY

园龄:1年1个月粉丝:0关注:0

Acwing

基础算法

快速排序模板

选定分界点,可以是l,r,l+r/2等

维护数组 使得分界点左边都<=分界点,右边都>=分界点

递归处理左右两边数组

代码实现如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5+10;
int n, m, k, t;
//快速排序
void quick_sort1(int q[], int l, int r){
    //边界不满足左边小,直接返回
    if (l >= r) return;
    //第一步,确定边界
    //tips1:由于i和j都是先自减或自增后判断,初始时i、j往边界两端扩一步
    int i = l - 1, j =  r + 1, x = q[l];
    //第二步,划分区间,使得一边小于x,一边大于x;
    while (i < j)
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    //第三步,递归处理两边
    quick_sort1(q, l, j), quick_sort1(q, j + 1, r);
}

int main(){
    ios;
    int a[N];
    scanf("%d",&n);//scanf比cin快哦
    for(int i = 0;i < n;i ++){
        scanf("%d",&a[i]);
    }
    quick_sort1( a, 0, n - 1);
    for(int i = 0;i < n;i ++){
        printf("%d ",a[i]);
    }
    return 0;
}

快速选择模板(第k大的数)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10;
int n, m, k, t;
int q[N];
int quick_sort(int l,int r,int k){
    if(l == r) return q[l];
    int x = q[l],i = l - 1, j = r + 1;
    while (i < j){
        while (q[++ i] < x);//
        while (q[-- j] > x);//这里两处漏了分号 ,一直报错没发现,人麻了
        if(i < j) swap (q[i] , q[j]);
    }
    int lenleft = j - l + 1;
    if(k <= lenleft) return quick_sort(l, j, k);
    else return quick_sort(j + 1, r, k - lenleft);
}
int main(){
    ios;
    cin >> n >> k;
    for(int i = 0;i < n;i ++){
        cin >> q[i];
    }
    cout << quick_sort(0,n - 1,k);
    return 0;
}

归并排序

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
int q[N];
int tmp[N];//辅助数组,与快排不同的一点
void mergesort(int q[], int l ,int r){
    if(l == r) return ;//一个数不用比

    int mid = (l + r) >> 1;
    //递归
    mergesort(q, l, mid);mergesort(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(int i = l, j = 0;i <= r;i ++ ,j ++ ) q[i] = tmp[j];//注意别写成i = 0了
}
int main(){
    ios;
    cin >> n;
    for(int i = 0 ;i < n;i ++) cin >> q[i];
    mergesort(q,0,n-1);
    for(int i = 0;i < n;i ++) cout << q[i] << " ";
    return 0;
}

逆序对数量(归并排序的应用)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
int q[N];
int tmp[N];//辅助数组,与快排不同的一点
ll mergesort(int q[], int l ,int r){
    if(l == r) return 0;

    int mid = (l + r) >> 1;
    ll res = mergesort(q, l, mid) + mergesort(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 ++];
            res += mid - i + 1;//主要区别
        }
    }
    while (i <= mid) tmp[k ++] = q[i ++];
    while (j <= r) tmp[k ++] = q[j ++];
    for(int i = l, j = 0;i <= r;i ++ ,j ++ ) q[i] = tmp[j];//注意别写成i = 0了
    
    return res;
}
int main(){
    ios;
    cin >> n;
    for(int i = 0 ;i < n;i ++) cin >> q[i];
    cout << mergesort(q,0,n-1) << endl;
//    for(int i = 0;i < n;i ++) cout << q[i] << " ";
    return 0;
}

高精度加法

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
vector<int> add(vector<int> &A,vector<int> &B){//int &a意思是定义一个引用 //引用相当于指针再取值 他和被引用的变量都是表示同一块内存
	vector<int> C;
	int tmp = 0;//进位
	for(int i = 0;i < A.size() || i < B.size();i ++){
		if(i < A.size()) tmp += A[i];
		if(i < B.size()) tmp += B[i];
		C.push_back(tmp % 10);
		tmp /= 10;
	}
	if(tmp) C.push_back(tmp);
	return C;
}
int main()
{
	ios;
	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');	
	auto C = add(A,B);
	for(int i = C.size() - 1;i >= 0;i --) cout << C[i];
    return 0;
}

高精度减法

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
bool cmp(vector<int> &A,vector<int> &B){
	if(A.size() != B.size()) return A.size() > B.size();
	else{
		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;
	int tmp = 0;
	for(int i = 0;i < A.size();i ++){//tmp表示借位
		tmp = A[i] - tmp;
		if(i < B.size()) tmp -= B[i];
		c.push_back((tmp + 10) % 10);
		if(tmp < 0) tmp = 1;
		else tmp = 0;
	}
	while (c.size() > 1&&c.back() == 0) c.pop_back();//去除前导零,>1是因为只有一个0的情况要输出0
	
	return c;
}
int main()
{
	ios;
	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');	
	auto C = sub(A,B);
	if(cmp(A,B)){
		auto C = sub(A,B);
		
		for(int i = C.size() - 1;i >= 0;i --) cout << C[i];
	}else{
		auto C = sub(B,A);
		cout << "-";
		for(int i = C.size() - 1;i >= 0;i --) cout << C[i];
	}
    return 0;
}

数的范围(二分)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
int q[N];
int main(){
	cin >> n >> m;
	for(int i= 0 ;i < n ;i ++){
		cin >> q[i];
	}
	
	while(m --){
		int x;
		cin >> 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 << " ";
			
			int l = 0, r = n - 1;
			while(l < r){
			int mid = l + r + 1 >> 1;//different,防止更新后还是[l,r]造成死循环
			if(q[mid] <= x) l = mid;//即取l = mid时mid = (l + r + 1)/2,r = mid 时mid = (l + r)/2
			else r = mid - 1;
			}			
			cout << l << endl;
		}
			
	}
}
//数的三次方根(浮点二分)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
ll a[200010], b[200010], c[200010], cnt[200010];
int main(){
    double x;
    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;
}

计算二进制中 1 的个数(位运算应用,重点!!!!)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 100010;
int n, m, k, t;
int lowbit(int x){
    return x & -x;
}
int main()
{ //x & -x = x & (~x + 1) // lowbit(x)运算,返回x的最后一位
//应用,统计1的个数
    cin >> n;
    while(n --){
        int x;
        cin >> x;
        int res = 0;
        while(x) x -= lowbit(x),res ++;//减去x最后一位1

        cout << res << " ";
    }
    return 0;
}

补充知识

n >> k & 1 求二进制第 k 位数字

前缀和 子矩阵和(略)

差分&差分矩阵

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10,M = 1e5+10;
int n, m, k, t;
int a[N], b[N];
void insert(int l,int r,int c){
    b[l] += c;
    b[r + 1] -= c;//[l,r]中间只用b[l]+c后面都会加c,最后r+1要减回去
}
int main()
{
    ios;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for (int i = 1; i <= n; i++)
    {
        b[i] = a[i] - a[i - 1];
    }

    while (m--)
    {
        int l, r, c;
        cin >> l >> r >> c;
        // b[l] += c;
        // b[r + 1] -= c;
        insert(l,r,c);
    }

    int sum = b[0];
    for (int i = 1; i <= n; i++)
    {
        sum += b[i];
        cout << sum << ' ';
    }
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1000 + 10,M = 1e5+10;
int n,m,k,t;
int a[N][N], b[N][N];
int q;
int main()
{
    cin >> n >> m >> q;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            scanf("%d", &b[i][j]);
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            a[i][j] = b[i][j] - b[i - 1][j] - b[i][j - 1] + b[i - 1][j - 1];
        }
    }

    while (q--)
    {
        int x1, y1, x2, y2, c;
        cin >> x1 >> y1 >> x2 >> y2 >> c;
        a[x1][y1] += c;
        a[x2 + 1][y1] -= c;
        a[x1][y2 + 1] -= c;
        a[x2 + 1][y2 + 1] += 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] + a[i][j];
            cout << b[i][j] << ' ';
        }
        cout << endl;
    }
    return 0;
}

双指针算法

1.最长连续不重复子序列

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10,M = 1e5+10;
int n, m, k, t;
int a[N],s[N];
int main()
{
    cin >> n;
    for(int i = 0;i < n;i ++){
		cin >> a[i];
	}
	int res = 0;
	for(int i = 0,j = 0;i < n;i ++){
		s[a[i]] ++;
		while(s[a[i]] > 1){
			 s[a[j]] --;
			 j ++;
		}
		res = max(res , i - j + 1);
	}
	cout << res << endl;
    return 0;
}
//  双指针算法
//for(int i = 0,j = 0;i < n;i ++){
//	while(j < i && check(i,j) ) j ++;
//  // 每道题具体逻辑
// }

2.数组元素目标和

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10,M = 1e5+10;
int n, m, k, t;
int a[N],b[N];
int main()
{
    cin >> n >> m >> t;
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
    }
    for (int i = 0; i < m; i++)
    {
        scanf("%d", &b[i]);
    }

    for (int i = 0, j = m - 1; i < n; i++)
    {
        while (j >= 0 && a[i] + b[j] > t)
            j--;
        if (a[i] + b[j] == t)
            cout << i << ' ' << j;
    }
    return 0;
}

3.判断子序列

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10,M = 1e5 + 10;
int n, m, k, t;
int a[N],b[N];
int main(){
    cin >> n >> m;
    for(int i = 0;i < n;i ++) scanf("%d",&a[i]);
    for(int j = 0;j < m;j ++) scanf("%d",&b[j]);
    int i = 0,j = 0;
    while(i < n && j < m)
    {
        if(a[i]==b[j])i ++,j ++;
        else j ++;
    }
    if(i == n) cout<<"Yes";
    else cout<<"No";
    return 0;
}

离散化(区间和)

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 3e5 + 10;
int n, m, k, t;
int a[N],s[N];
vector<int> alls;
vector<pii> add,q;
int find (int x){
    int l = 0,r = alls.size() - 1;
    while(l < r){
        int mid = l + r >> 1;
        if(alls[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1;
}
void work() 
{
    cin >> n >> m;
    for(int i = 0;i < n;i ++){
        int x,c;
        cin >> x >> c;
        add.push_back({x,c});
        alls.push_back(x);
    }
    for(int i = 0;i < m;i ++){
        int l,r;
        cin >> l >> r;
        q.push_back({l,r});
        alls.push_back(l);
        alls.push_back(r);
    }
    //离散化x,l,r
    //去重(离散化核心:去重加二分查找)
    sort(alls.begin(),alls.end());
    alls.erase(unique(alls.begin(),alls.end()),alls.end());

    //处理插入
    for(auto it : add){
        int x = find(it.first);
        a[x] += it.second;
    }

    //预处理前缀和
    for(int i = 1;i <= alls.size();i ++){
        s[i] = s[i-1] + a[i];
    }
    //询问
    for(auto it : q){
        int l = find(it.first),r = find(it.second);
        cout << s[r] - s[l - 1] << endl;
    }
}
int main()
{
    ios;
    int T = 1;
    //cin >> T;
    while(T --){
        work();
    }
    return 0;
}

区间合并

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10,M = 1e5+10;
int n, m, k, t;
int a[N],s[N];
int l, r;
vector<PII> segs;
void merge(vector<PII> &segs)
{
    vector<PII> res;
    sort(segs.begin(), segs.end());
    int st = -2e9, ed = -2e9;//数据范围是10^9

    for (auto seg : segs)
    {
        if (ed < seg.first)
        {
            if (st != -2e9)
                res.push_back({st, ed});
            st = seg.first, ed = seg.second;
        }
        else
            ed = max(ed, seg.second);
    }
    if (st != -2e9)//防止输入数组的没有区间
        res.push_back({st, ed});//遍历完最后还更新了一次st和ed(最后一组),别忘了把这个加进去
    segs = res;
}
int main(){
    cin >> n;
    for (int i = 0; i < n; i ++){
        cin >> l >> r;
        segs.push_back({l, r});
    }

    merge(segs);
    cout << segs.size() << endl;
    return 0;
}

数据结构

单链表

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 3e5 + 10;
int n, m, k, t;
int head,e[N],ne[N];//head表示头结点
int idx;
// void init(){
//     head = -1;
//     idx = 0;//如果这样的话,第k个插入的数下标为k-1
// }
// void hdinsert(int x){//头插
//     e[idx] = x;
//     ne[idx] = head;
//     head = idx ++;
// }
void init(){
    ne[0] = -1;//e[0] = 0,但是没意义,最后不输出就行
    idx = 1;//这样的话就把合并了两种插入模式
}
//插在下标为 k 的这点后面
int insert(int k,int x){
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx ++;
}
//下标为 k 的这点后面的一个点删掉,这题删掉点idx不变(一般不管)
int remove(int k){
    //if(k == 0) head = ne[head];//如果合并了两种插入方法就不用考虑这个情况了
    ne[k] = ne[ne[k]];
}
void work() 
{
    init();
    cin >> n;
    char ss;
    while(n --)
    {
        int x, k;
        cin >> ss;
        if(ss == 'H')cin >> x,insert(0,x);
        else if(ss == 'I')cin >> k >> x,insert(k,x);
        else cin >> k,remove(k);
    }
    k = ne[0];
    while(k != -1)
    {
        cout << e[k] << ' ';
        k = ne[k];
    }
}
int main()
{
    ios;
    int T = 1;
    //cin>> T;
    while(T --){
        work();
    }
    return 0;
}

双链表

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 3e5 + 10;
int n, m, k, t;
int v[N], l[N], r[N], idx;//用数组来分别表示值和下标更加方便
int x;
string str;
void init()//初始化
{
	r[0] = 1;
	l[1] = 0;// 0 1代表恒定不变的头节点和尾节点(哑节点)
	idx = 2;// 0 1已经占用了2个 idx,故 idx 从 2 开始
}

void insert(int k, int x)
{
	v[idx] = x;
	l[idx] = k;
	r[idx] = r[k];
	l[r[k]] = idx;
	r[k] = idx ++;
}

void remove(int k)//把第 k 个插入的节点删除
{
	r[l[k]] = r[k];
	l[r[k]] = l[k];
}
void work() 
{
    init();
    cin >> n;
    while(n --)
    {
        cin >> str;
        if(str == "L")cin >> x,insert(0,x);
        else if(str == "R")cin >> x,insert(l[1],x);
        else if(str == "IR")cin >> k >> x,insert(k + 1,x);
        else if(str == "IL")cin >> k >> x,insert(l[k + 1],x);
        else cin >> k,remove(k + 1);
    }
    k = r[0];
    while(k != 1)
    {
        cout << v[k] << ' ';
        k = r[k];
    }
}
int main()
{
    ios;
    int T = 1;
    //cin >> T;
    while(T --){
        work();
    }
    return 0;
}

表达式求值(栈的应用)

`#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10;
int n, m, k, t;
stack<int> num;
stack<char> op;
void eval()
{
    int b = num.top();
    num.pop();
    int a = num.top();
    num.pop();
    char c = op.top();
    op.pop();
    if(c=='+')a += b;
    else if(c=='-')a -= b;
    else if(c=='*')a *= b;
    else a /= b;
    num.push(a);
}
void work() 
{
   unordered_map<char,int> pr{{'+',1},{'-',1},{'*',2},{'/',2}};
   string ss;
   cin >> ss;
   for(int i = 0;i < ss.size();i ++){
        auto c = ss[i];
        if(isdigit(c)){
            int x = 0,j = i;
            while(j < ss.size()&&isdigit(ss[j]))
                x = x * 10 + ss[j ++] - '0';
            i = j - 1;
            num.push(x);
        }
        else if(ss[i]=='(') op.push(ss[i]);
        else if(ss[i]==')'){
            while(op.top()!='(') eval();
            op.pop();
        }
        else{    
            while(op.size()&&pr[op.top()] >= pr[ss[i]])//判断优先级
                eval();
            op.push(ss[i]);
        }
    }
    while(op.size())   eval();
    cout << num.top();
}
int main()
{
    ios;
    int T = 1;
    //cin >> T;
    while(T --){
        work();
    }
    return 0;
}

数组模拟队列

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10;
int n, m, k, t;
int q[N],hh = 0,tt = -1;//hh队头,tt队尾
int main(){
    string str;
    cin >> n;
    while(n --)
    {
        cin >> str;
        int x;
        if(str == "push")cin >> x,q[++ tt]=x;
        else if(str == "pop")hh ++;
        else if(str == "empty")
            if(tt < hh)cout << "YES" << endl;
            else cout << "NO" << endl;
        else cout << q[hh] << endl;
    }
    return 0;
}

单调栈

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10;
int n, m, k, t;
stack<int> s;
int main(){
    cin >> n;
    while (n --)
    {
        int x;
        cin >> x;
        while (!s.empty() && x <= s.top())
            s.pop();
        if (s.empty())
            cout << -1 << " ";
        else
            cout << s.top() << " ";
        s.push(x);
    }
    return 0; 
}

滑动窗口(单调队列/双端队列)

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
int s[N];
deque<int> q;
int main(){
    cin >> n >> k;
    for(int i = 0;i < n;++ i)cin >> s[i];
    for(int i = 0;i < n;++ i)
    {
        while(!q.empty() && s[i] <= s[q.back()]) q.pop_back();
        q.push_back(i);
        if(q.front() + k == i) q.pop_front();
        if(i >= k - 1) cout << s[q.front()] << " ";
    }
    cout << endl;
    q.clear();
    for(int i = 0;i < n;++ i)
    {
        while(!q.empty() && s[i] >= s[q.back()]) q.pop_back();
        q.push_back(i);
        if(q.front() + k == i) q.pop_front();
        if(i >= k - 1)cout << s[q.front()] << " ";
    }
    return 0; 
}

KMP算法

#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10;
int n, m, k, t;
int main(){
    string s, ss;
    cin >> m >> ss >> n >> s;
    //求ne[]
    int ne[N] = {0};
    for (int i = 1, j = 0; i < m; i++)
    {
        while (j && ss[i] != ss[j])
            j = ne[j - 1];
        if (ss[i] == ss[j])
            j++;
        ne[i] = j;
    }

    for (int i = 0, j = 0; i < n; i++)
    {
        while (j && s[i] != ss[j])//j的含义是j没通过next跳到初始位置(也就是说没有重新开始匹配)
            j = ne[j - 1];
        if (s[i] == ss[j])
            j++;
        if (j == m)
            cout << i - j + 1 << ' ';
    }
    return 0;

}

搜索与图论

DFS

void dfs(int step)    //步长
{
    if(/*跳出循环的条件*/){
        return;    //return十分关键,否则循环将会无法跳出
    }
    /*函数主体
    对功能进行实现*/
    for(/*对现有条件进行罗列*/){
        if(/*判断是否合理*/){
            //将条件修改
            dfs(/*新的step*/)
            /*!重中之重,当跳出那层循环后将数据全部归位*/
        }    
    }
}
//例如,acwing排列数字
const int N = 10;
int a[N],n;
bool st[N];
void dfs(int x)
{
    if(x == n)
    {
        for(int i = 0;i < n;i++)cout << a[i] << ' ';
        cout << endl;
        return;
    }
    for(int i = 1;i <= n;i++)
    {
        if(!(st[i]))
        {
            a[x] = i;
            st[i] = true;
            dfs(x+1);
            st[i] = false;
        }
    }
}
int main()
{
    cin >> n;
    dfs(0);
    return 0;
}

DFS 矩阵 模板

int f[4][2]={{0,1},{0,-1},{1,0},{-1,0}};    //用于判断下一步怎么走向几个方向走就是几个数据
void dfs(int x,int y){        //进入点的坐标
    if(/*跳出循环的条件*/){
        /*作出相应操作*/
        return;        //不要忘了return
    }
    for(int i=0;i</*f的长度*/;i++){
        int x0=x+f[i][0];    
        /*此处是更新点的坐标,注意是直接让原来的点加上这个数据,不是直接等于*/
        int y0=y+f[i][1];
        if(/*用新坐标x0,y0判断是否符合条件*/){
            dfs(x0,y0);    //用新的坐标进行递归
        }
    }
}

BFS

AcWing 844. 走迷宫

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
typedef long long ll;
typedef pair<int,int>PII;
int g[N][N],d[N][N];
int n, m;
queue <PII> q;
int bfs()
{
    memset(d,-1,sizeof d);
    d[0][0] = 0;
    q.push({0,0});
    int dx[4] = {-1,0,1,0};
    int dy[4] = {0,1,0,-1};

    while(!q.empty())
    {
        auto t = q.front();
        q.pop();
        for(int i = 0;i < 4;i++)
        {
            int x = t.first + dx[i],y = t.second + dy[i];
            if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)
            {
                d[x][y] = d[t.first][t.second]+1;
                q.push({x,y});
            }
        }
    }
    return d[n-1][m-1];
}
int main()
{
    cin >> n >> m;
    for(int i = 0;i < n;i++)
    {
        for(int j = 0;j < m;j++)
        {
            cin >> g[i][j];
        }
    }

    cout << bfs() << endl;
    return 0;
}

AcWing 845. 八数码

#include <bits/stdc++.h>
using namespace std;
int bfs(string s)
{
    string sl = "12345678x";
    queue<string>q;
    unordered_map<string,int>d;
    q.push(s);
    d[s] = 0;
    int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        int distance = d[t];
        if(t == sl) return distance;

        int k = t.find('x');
        int x = k/3,y = k%3;
        for(int i = 0;i < 4;i++)
        {
            int a = x+dx[i],b = y+dy[i];
            if(a >= 0 && a < 3 && b < 3 && b >= 0)
            {
                swap(t[k],t[a*3+b]);
                if(!d.count(t))
                {
                    d[t] = distance+1;
                    q.push(t);
                }
                swap(t[k],t[a*3+b]);
            }
        }
    }
    return -1;
}
int main ()
{
    string s;
    for(int i = 0;i < 9;i++)
    {
        char c;
        cin >> c;
        s += c;
    }
    cout << bfs(s) << endl;
    return 0;
}

本文作者:Go1NgZCY

本文链接:https://www.cnblogs.com/going-zcy/p/18062145

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Go1NgZCY  阅读(23)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起