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 = 5e3;

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;
  

二维区间修改,单点查询

利用二维差分进行更新,更新和查询复杂度复杂度 l o g 2 2 log^2_2 log22

#include<bits/stdc++.h>

using namespace std;
#define ll long long 

const int N = 5e3+10;
ll tree[N][N];
ll t,n,m;

ll lowbit(ll x) 
	return -x & x;


void add(ll x,ll y,ll k) //单点更新 
	while(x <= n) 
		ll temp = y;
		while(y <= m) 
			tree[x][y] += k;
			y += lowbit(y);
		
		x += lowbit(x);
		y = temp;
	


void updata(ll x1,ll y1,ll x2,ll y2,ll k) //矩阵更新 
	add(x1,y1,k);
	add(x1,y2 + 1,-k);
	add(x2 + 1,y1,-k);
	add(x2 + 1,y2 + 1,k); 


ll query(ll x,ll y) //单点查询
	ll ans = 0;
	while(x) 
		ll temp = y;
		while(y) 
			ans += tree[x][y];
			y -= lowbit(y);
		
		x -= lowbit(x);
		y = temp;
	
	return ans;



int main()

	ll x1,x2,y1,y2,k;
	memset(tree,0,sizeof tree);
	scanf("%lld%lld",&n,&m);//n X m的矩阵 
	int op;
	while(~scanf("%d",&op)) 
		if(op == 1) 
			scanf("%lld%lld%lld%lld%lld",&x1,&y1,&x2,&y2,&k);
			updata(x1,y1,x2,y2,k);
		
		else 
			scanf("%lld%lld",&x1,&y1);
			ll kk = query(x1,y1);
			printf("%lld\\n",kk);
		
	
	return 0;

二维区间修改,区间查询

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

const int N = 3e3;

ll n,m;
ll tree[N][N][4];

ll read()

	ll X=0; bool flag=1; char ch=getchar();
	while(ch<'0'||ch>'9') if(ch=='-') flag=0; ch=getchar();
	while(ch>='0'&&ch<='9') X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();
	if(flag) return X;
	return ~(X-1);


ll write(ll X)

	if(X<0) putchar('-'); X=~(X-1);
	int s[65],top=0;
	while(X) s[++top]=X%10; X/=10;
	if(!top) s[++top]=0;
	while(top) putchar(s[top--]+'0');



inline ll lowbit(ll x) 
	return -x & x;


void add(ll x,ll y,ll k) 
	for(ll i = x;i <= n; i += lowbit(i)) 
		for(ll j = y;j <= m; j += lowbit(j)) 
			tree[i][j][0] += k;
			tree[i][j][1] += k * x;
			tree[i][j][2] += k * y;
			tree[i][j][3] += k * x * y;
		
	


void updata(ll x1,ll y1,ll x2,ll y2,ll k) 
	add(x1,y1,k);
	add(x1,y2 + 1,-k);
	add(x2 + 1,y1,-k);
	add(x2 + 1,y2 + 1,k);


ll ask(ll x,ll y) 
	ll ans = 0;
	for(ll i = x;i; i -= lowbit(i)) 
		for(ll j = y;j; j -= lowbit(j)) 
			ans += (x + 1) * (y + 1) * tree[i][j][0] 
				-  (y + 1) * tree[i][j][1] 
				-  (x + 1) * tree[i][j][2] 
				+  			 tree[i][j][3];
		
	
	return ans;


ll query(ll x1,ll y1,ll x2,ll y2) 
	return ask(x1-1,y1-1) - ask(x1 - 1,y2) - ask(x2,y1 - 1) + ask(x2,y2);


int main()

	n = read();
	m = read();
	int op;
	ll x1,x2,y1,y2,k;
	while(~scanf("%d",&op)) 
		if(op == 1) 
			scanf("%lld%lld%lld%lld%lld",&x1,&y1,&x2,&y2,&k);
			updata(x1,y1,x2,y2,k);
		
		else 
			scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
			ll kk = query(x1,y1,x2,y2);
			printf("%lld\\n",kk);
		
	
	
	
	
	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)计算几何

记TJPUのACM新生赛——Stay young, stay simple

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

-----------------------奇怪の模板-----------------------

WPF自定义控件の重写原生控件样式模板

UVA 11178 Morley's Theorem(旋转+直线交点)