MangataのACM模板

Posted MangataTS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MangataのACM模板相关的知识,希望对你有一定的参考价值。

文章目录


本篇文章主要是Mangata平时写代码所用到的代码模板库,如有不对请在评论区指出
 
先放一个我的 常数优化的博客: 传送门
 
再放一个我的 代码格式博客: 传送门
 

数据结构

并查集

并查集是一种集合数据结构,通过并查集我们可以快速查询两个元素是否是一个集合,下面是Mangata常用的板子

/*
    作者:Mangata
    路径压缩并查集
*/
#include<cstdio>

const int N = 10005;//节点数 
int fa[N],n;

void init(int len) {//初始化,先让每个位置的父节点等于自身 
    for(int i=0; i<=n; ++i)
        fa[i] = i;
}

int find(int x) {//查找x的祖先节点 
    int t = x;//路径压缩
    while(t != fa[t]) 
        t = fa[t];
    while(x != fa[x]) {
        int temp = fa[x];
        fa[x] = t;
        x = temp;
    }
    return x;
}

void merge(int a,int b) {//将x和y合并 
    a=find(a),b=find(b);
    if(a != b) {
        fa[b] = a;
        n--;
    }
}

int main()
{
    int t,m,a,b;
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d",&n,&m);
        init(n);
        for(int i = 1; i <= m; ++i) {
            scanf("%d%d",&a,&b);
            merge(a,b);
        }
        printf("%d\\n",n);//输出不同类别的总数目
    }
    
    return 0;
}

树状数组

二维单点修改,区间查询

例题:传送门

Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 5000;

ll tree[N][N<<2];
int n,m;

int lowbit(int x) {
	return -x & x;
}

inline void updata(int x,int y,int k) {
	while(x <= n) {
		int temp = y;
		while(y <= m) {
			tree[x][y] += k;
			y += lowbit(y);
		}
		x += lowbit(x);
		y = temp;
	}
}

inline ll get(int x,int y) {
	ll ans = 0;
	while(x) {
		int temp = y;
		while(y) {
			ans += tree[x][y];
			y -= lowbit(y);
		}
		x -= lowbit(x);
		y = temp;
	}
	return ans;
}

int main()
{
	scanf("%d%d",&n,&m);
	int a,b,c,d,op;
	while(~scanf("%d",&op)) {
		if(op == 1) {
			scanf("%d%d%d",&a,&b,&c);
			updata(a,b,c);
		}
		else {
			scanf("%d%d%d%d",&a,&b,&c,&d);
			printf("%lld\\n",get(c,d)-get(c,b-1)-get(a-1,d) + get(a-1,b-1));
		}
	}
	return 0;
 } 

线段树

单点修改,区间查询

例题:HDU1754

#include<bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 2000005;
int n,m;
int a[N],tree[N << 2];

void push_up(int k) {
    tree[k] = max(tree[k<<1],tree[k<<1|1]);
}
void build(int k, int l,int r) {
    if(l == r) {
        tree[k] = a[l];
    }
    else {
        int mid = l + ((r-l)>>1);
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        push_up(k);
    }
}

void updata(int p,int v,int l,int r,int k) {
    if(l == r) {
        a[p] += v, tree[k] += v;
    }
    else {
        int mid = l + ((r-l)>>1);
        if(p <= mid) {
            updata(p,v,l,mid,k<<1);
        }
        else {
            updata(p,v,mid+1,r,k<<1|1);
        }
        push_up(k);
    }
}

int query(int L, int R,int l,int r,int k) {
    if(L <= l && R >= r) {
        return tree[k];
    }
    else {
        int ans = -INF;
        int mid = l+r >>1;
        if(L <= mid) {
            ans = max(ans,query(L,R,l,mid,k<<1));
        }
        if(R > mid) {
            ans = max(ans,query(L,R,mid+1,r,k<<1|1));
        }
        return ans;
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m)) {
        for(int i = 1;i <= n; ++i) {
            scanf("%d",&a[i]);
        }
        build(1,1,n);
        char op;
        int l,r;
        while(m--) {
            cin>>op;
            if(op == 'Q') {
                scanf("%d%d",&l,&r);
                printf("%d\\n",query(l,r,1,n,1));
            }
            else if(op == 'U'){
                scanf("%d%d",&l,&r);
                updata(l,r-a[l],1,n,1);
            }
        }
    }
    return 0;
}

区间更新、区间查询

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e6+10;

ll tree[N<<2],tag[N<<2];
ll a[N];

inline ll ls(ll p) {return p<<1;}
inline ll rs(ll p) {return p<<1|1;}

void push_up_min(ll p) {//向上更新操作 
	tree[p] = min(tree[ls(p)],tree[rs(p)]);
}

void build(ll p,ll l,ll r) {//建树操作 
	if(l == r) {
		tree[p] = a[l];
		return;
	}
	ll mid = l + r >> 1;
	build(ls(p),l,mid);
	build(rs(p),mid+1,r);
	push_up_min(p);
}

inline void push_down(ll p,ll l,ll r) {//向下更新操作
	if(tag[p]) {
		tag[ls(p)] += tag[p];
		tag[rs(p)] += tag[p];
		
		tree[ls(p)] += tag[p];
		tree[rs(p)] += tag[p];
		tag[p] = 0;
	}
	//更新两个儿子节点的tag和tree值
}

void updata(ll L ,ll R ,ll l ,ll r ,ll p ,ll k) {//[L,R]是我们想要修改的区间,
	if(L <= l && R >= r) {				//[l,r]是我们目前搜索到的区间
		tree[p] += k;
		tag[p] += k;
		return;
	}
	push_down(p,l,r);//回溯前往下传递更新
	ll mid = l + r >> 1;
	if(L <= mid) updata(L,R,l,mid,ls(p),k);//如果我们想修改的区间比当前的中间节点小or等于那么就查询 
	if(R >  mid) updata(L,R,mid+1,r,rs(p),k);//如果我们想修改的区间比当前中间节点大那么就查询 
	push_up_min(p);//回溯后往上传递更新
}

ll query(ll L, ll R,ll l,ll r,ll p) {//[L,R]是我们要查询的区间,[l,r]是当前节点存储的区间 
	ll res = 0x3f3f3f3f3f3f3f3f;
	if(L <= l && R >= r) return tree[p];
	ll mid = l + r >> 1;
	push_down(p,l,r);
	if(L <= mid)
		res = min(res,query(L,R,l,mid,ls(p)));
	if(R > mid)
		res = min(res,query(L,R,mid+1,r,rs(p)));
	return res;
}
int n,m;

int main()
{
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n; ++i) {
		scanf("%lld",&a[i]);
	}
	build(1,1,n);
	int q;
	ll l,r,k;
	int fg = 0;
	for(int i = 1;i <= m; ++i) {
		scanf("%lld%lld%lld",&k,&l,&r);
		if(fg) continue;
		if(query(l,r,1,n,1) >= k)
			updata(l,r,1,n,1,-k);
		else fg = i;
	}
	if(fg) {
		printf("-1\\n%d\\n",fg);
	}
	else puts("0");
	return 0;
}

 

主席树(区间第k小数模板)

#include<bits/stdc++.h>
using namespace std;

const int N = 200005;
const int M = 200005;
int n记TJPUのACM新生赛——Stay young, stay simple

小鑫の日常系列故事——排名次

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段1——vue主模板

VSCode自定义代码片段2——.vue文件的模板

VSCode自定义代码片段(vue主模板)