Aurora的模板集合

模板题

数学

快速幂

传送门:P1226 【模板】快速幂||取余运算

ll ksm(ll a, ll b, ll mod) {
	ll ans = 1;
	while(b) {
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod; b >>= 1;
	}
	return ans % mod;
}

图论

LCA

传送门:P3379 【模板】最近公共祖先(LCA)

code:

void dfs(int u) {      // 倍增预处理
	for(int i = 1; i <= 21; i++) f[u][i] = f[f[u][i - 1]][i - 1];
	for(int i = h[u]; i; i = e[i].nex) {
		if(e[i].to == f[u][0]) continue;
		f[e[i].to][0] = u; de[e[i].to] = de[u] + 1;
		dfs(e[i].to);
	}
}

void make_it() {      // 另一种倍增预处理
	de[s] = 1; f[s][0] = s;
	dfs(s);
//	for(int j = 1; j <= 21; j++)
//		for(int i = 1; i <= n; i++)
//			f[i][j] = f[f[i][j - 1]][j - 1];  不在DFS中处理完f数组而是在这里处理也是可以的
}

int query(int x, int y) {    // 查询
	if(de[x] < de[y]) swap(x, y);
	for(int i = 21; i >= 0; i--) if(de[x] - (1 << i) >= de[y]) x = f[x][i];
	if(x == y) return x;
	for(int i = 21; i >= 0; i--) if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
	return f[x][0];
}

缩点

Tarjan

传送门:P3387 【模板】缩点

code:

void tarjan(int u) {     // tarjan核心代码
	low[u] = dfn[u] = ++dfncnt; sta.push(u);
	for(int i = h[u]; i; i = e[i].nex) {
		int v = e[i].to;
		if(!dfn[v]) {tarjan(v); low[u] = min(low[u], low[v]);}
		else if(!scc[v]) low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u]) {
		scccnt++;
		while(sta.top() != u) {p[scccnt] += a[sta.top()]; scc[sta.top()]= scccnt; siz[scccnt]++; sta.pop();}
		p[scccnt] += a[sta.top()]; scc[sta.top()] = scccnt; siz[scccnt]++; sta.pop();
	}
}

void MakeScc() {    // 缩点,建立缩点后的图
	for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i);
	for(int i = 1; i <= m; i++) {
		int x = scc[e[i].from], y = scc[e[i].to];
		if(x != y) addd(x, y);	
	}
}

数据结构

ST表

传送门1:P3865 【模板】ST表

传送门2:ST 表-OI Wiki

操作:查询区间最大值。

code:

void Pre() {  // log_2(x) 预处理对数
	logn[1] = 0; logn[2] = 1;
	for(int i = 3; i <= 100005; i++) logn[i] = logn[i >> 1] + 1;
}

void SetUp {  // 建表
    pre();
    for(int i = 1; i <= n; i++) f[i][0] = a[i];
	for(int j = 1; j <= 21; j++)
		for(int i = 1; i + (1 << j) - 1 <= n; i++)
			f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}

void query(int x, int y) {    // 查询
    int s = logn[y - x + 1];
	printf("%d\n", max(f[x][s], f[y - (1 << s) + 1][s]));
}

树状数组

树状数组1

传送门1:P3374 【模板】树状数组 1

传送门2:树状数组-OI Wiki

操作:

  1. 将某一个数加上\(x\)
  2. 求出某区间每一个数的和

code:

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

void build() {
	for(int i = 1; i <= n; i++) {
		t[i] = t[i] + c[i];
		int j = i + lowbit(i);
		if(j <= n) t[j] = t[j] + t[i];
	}
}

void update(int x, int k) {
	while(x <= n) {
		t[x] = t[x] + k;
		x = x + lowbit(x);
	}
}

int query(int x) {
	int ans = 0;
	while(x) {
		ans = ans + t[x];
		x = x - lowbit(x);
	}
	return ans;
}

树状数组2

转送门:P3368 【模板】树状数组 2

操作:

  1. 将某区间每一个数数加上\(x\)。
  2. 求出某一个数的值。

code:

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

void build() {
	for(ll i = 1; i <= n; i++) {
		t[i] = 0;
		ll j = i + lowbit(i);
		if(j <= n) t[j] = t[j] + t[i];
	}
}

void update(ll x, ll k) {
	while(x <= n) {
		t[x] = t[x] + k;
		x = x + lowbit(x);
	}
}

ll query(ll x) {
	ll ans = 0;
	while(x) {
		ans = ans + t[x];
		x = x - lowbit(x);
	}
	return ans;
}

线段树

线段树1

传送门:P3372 【模板】线段树 1

操作:

  1. 将某区间每一个数加上 \(k\)。
  2. 求出某区间每一个数的和。

code:

void build(ll u, ll l, ll r) {
	if(l == r) {
		tre[u].sum = read();
		return ;
	}
	ll lson = u << 1, rson = (u << 1) + 1, mid = (l + r) >> 1;
	build(lson, l, mid); build(rson, mid + 1, r);
	tre[u].sum = tre[lson].sum + tre[rson].sum;
}

void pushdown(ll u, ll l, ll r) {
	if(tre[u].lazy == 0 || l == r) return;
	ll lson = (u << 1), rson = (u << 1) + 1, mid = (l + r) >> 1;
	tre[lson].lazy += tre[u].lazy; tre[lson].sum = tre[lson].sum + tre[u].lazy * (mid - l + 1);
	tre[rson].lazy += tre[u].lazy; tre[rson].sum = tre[rson].sum + tre[u].lazy * (r - mid);
	tre[u].lazy = 0;
}

void update(ll u, ll l, ll r, ll x, ll y, ll k) {
	if(l >= x && r <= y) {
		tre[u].lazy = tre[u].lazy + k;
		tre[u].sum = tre[u].sum + k * (r - l + 1);
		return ;
	}
	ll lson = u << 1, rson = (u << 1) + 1, mid = (l + r) >> 1;
	pushdown(u, l, r);
	if(x <= mid) update(lson, l, mid, x, y, k);
	if(y > mid) update(rson, mid + 1, r, x, y, k);
	tre[u].sum = tre[lson].sum + tre[rson].sum;
}

ll query(ll u, ll l, ll r ,ll x, ll y) {
	if(l >= x && r <= y) return tre[u].sum;
	ll lson = u << 1, rson = (u << 1) + 1, mid = (l + r) >> 1, t1 = 0, t2 = 0;
	pushdown(u, l ,r);
	if(x <= mid) t1 = query(lson, l, mid, x, y);
	if(y > mid) t2 = query(rson, mid + 1, r, x, y);
	return t1 + t2;
}

线段树2

传送门:P3373 【模板】线段树 2

操作:

  1. 将某区间每一个数乘上\(x\)
  2. 将某区间每一个数加上\(x\)
  3. 求出某区间每一个数的和

code:

void build(int tre,int l,int r) {
	t[tre].lazy2 = 1;
	if(l == r) {
		t[tre].sum = read() % p;
		return ;
	}
	int mid = (l + r) >> 1;
	build(lson,l,mid); build(rson,mid + 1,r);
	t[tre].sum = (t[lson].sum + t[rson].sum) % p;
}

void pushdown(int tre,int l,int r) {
	int mid = (l + r) >> 1;
	t[lson].lazy1 = (t[lson].lazy1 * t[tre].lazy2 + t[tre].lazy1) % p;
	t[rson].lazy1 = (t[rson].lazy1 * t[tre].lazy2 + t[tre].lazy1) % p;
	t[lson].lazy2 = (t[lson].lazy2 * t[tre].lazy2) % p;
	t[rson].lazy2 = (t[rson].lazy2 * t[tre].lazy2) % p;
	t[lson].sum = ((t[lson].sum * t[tre].lazy2) % p + (t[tre].lazy1 * (mid - l + 1)) % p) % p;
	t[rson].sum = ((t[rson].sum * t[tre].lazy2) % p + (t[tre].lazy1 * (r - mid)) % p) % p;
	t[tre].lazy1 = 0; t[tre].lazy2 = 1;
}

void updata1(int tre,int l,int r,int x,int y,int z) {
	if(l >= x && r <= y) {
		t[tre].sum = (t[tre].sum + (r - l + 1) * z) % p;
		t[tre].lazy1 = (t[tre].lazy1 + z) % p;
		return ;
	}
	pushdown(tre,l,r);
	int mid = (l + r) >> 1;
	if(x <= mid) updata1(lson,l,mid,x,y,z);
	if(y > mid) updata1(rson,mid + 1,r,x,y,z);
	t[tre].sum = (t[lson].sum + t[rson].sum) % p;
}

void updata2(int tre,int l,int r,int x,int y,int z) {
	if(l >= x && r <= y) {
		t[tre].sum = (t[tre].sum * z) % p;
		t[tre].lazy1 = (t[tre].lazy1 * z) % p;
		t[tre].lazy2 = (t[tre].lazy2 * z) % p;
		return ;
	}
	pushdown(tre,l,r);
	int mid = (l + r) >> 1;
	if(x <= mid) updata2(lson,l,mid,x,y,z);
	if(y > mid) updata2(rson,mid + 1,r,x,y,z);
	t[tre].sum = (t[lson].sum + t[rson].sum) % p;
}

int query(int tre,int l,int r,int x,int y) {
	if(l >= x && r <= y) return t[tre].sum;
	pushdown(tre,l,r);
	int mid = (l + r) >> 1,t1 = 0,t2 = 0;
	if(x <= mid) t1 = query(lson,l,mid,x,y);
	if(y > mid) t2 = query(rson,mid + 1,r,x,y);
	return (t1 + t2) % p;
}
上一篇:线段树合并


下一篇:LOJ #2341. 「WC2018」即时战略 交互+LCT+随机化