NOIP知识点&&模板整理【更新中】

NOIP知识点&&模板整理

数据结构


线段树1

#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
typedef long long ll;
ll read()
{
	char c = getchar(), last = ' ';
	ll ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
ll a[N];
namespace seg
{
	ll sum[N << 2], lazy[N << 2];
	void pushup(int cnt)
	{
		sum[cnt] = sum[cnt << 1] + sum[cnt << 1 | 1];
	}
	void pushdown(int cnt, int l, int r)
	{
		int mid = l + r >> 1;
		//sum[cnt] += lazy[cnt] * (r - l + 1);
		sum[cnt << 1] += lazy[cnt] * (mid - l + 1);
		sum[cnt << 1 | 1] += lazy[cnt] * (r - mid);
		lazy[cnt << 1] += lazy[cnt];
		lazy[cnt << 1 | 1] += lazy[cnt];
		lazy[cnt] = 0;
 	}
 	void build(int cnt, int l, int r)
 	{
 		if(l == r) 
		{
		 	sum[cnt] = a[l];
		 	return;
		}
 		int mid = l + r >> 1;
 		build(cnt << 1, l, mid);
 		build(cnt << 1 | 1, mid + 1, r);
 		pushup(cnt);
	 }
 	void add(int cnt, int l, int r, int nl, int nr, ll k)
 	{
 		if(l >= nl && r <= nr) 
 		{
 			sum[cnt] += (r - l + 1) * k;
 			lazy[cnt] += k;
 			return;
		}
		int mid = l + r >> 1;
		pushdown(cnt, l, r);
		if(nl <= mid) add(cnt << 1, l, mid, nl, nr, k);
		if(nr > mid) add(cnt << 1 | 1, mid + 1, r, nl, nr, k);
		pushup(cnt);
	}
	ll query(int cnt, int l, int r, int nl, int nr)
	{
		if(l >= nl && r <= nr) return sum[cnt];
		int mid = l + r >> 1;
		ll ans = 0;
		pushdown(cnt, l, r);
		if(nl <= mid) ans += query(cnt << 1, l, mid, nl, nr);
		if(nr > mid) ans += query(cnt << 1 | 1, mid + 1, r, nl, nr);
		return ans;
	}
}
int n, m;
int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i ++) a[i] = read();
	seg::build(1, 1, n);
	int opt, x, y;
	ll k, ans = 0;
	for(int i = 1; i <= m; i ++)
	{
		opt = read(), x = read(), y = read();
		if(opt == 1)
		{
			k = read();
			seg::add(1, 1, n, x, y, k);
		}
		else if(opt == 2)
		{
			ans = seg::query(1, 1, n, x, y);
			printf("%lld
", ans);
		}
	}
}

线段树2

#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
typedef long long ll;
ll read()
{
	char c = getchar(), last = ' ';
	ll ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
int n, m, p;
ll a[N];
namespace seg
{
	ll sum[N << 2], lazy1[N << 2], lazy2[N << 2];
	void pushup(int cnt)
	{
		sum[cnt] = (sum[cnt << 1] + sum[cnt << 1 | 1]) % p;
	}
	void pushdown(int cnt, int l, int r)
	{
		int mid = l + r >> 1;
		lazy1[cnt << 1] = ((lazy1[cnt << 1] * lazy2[cnt] % p) + lazy1[cnt] % p) % p;
		lazy1[cnt << 1 | 1] = ((lazy1[cnt << 1 | 1] * lazy2[cnt] % p) + lazy1[cnt]) % p;
		lazy2[cnt << 1] = lazy2[cnt << 1] * lazy2[cnt] % p;
		lazy2[cnt << 1 | 1] = lazy2[cnt << 1 | 1] * lazy2[cnt] % p;
		sum[cnt << 1] = ((lazy1[cnt] * (mid - l + 1) % p) + lazy2[cnt] * sum[cnt << 1] % p) % p;
		sum[cnt << 1 | 1] = ((lazy1[cnt] * (r - mid) % p) + lazy2[cnt] * sum[cnt << 1 | 1] % p) % p;
		lazy1[cnt] = 0; 
		lazy2[cnt] = 1;
 	}
 	void build(int cnt, int l, int r)
 	{
 		lazy2[cnt] = 1;
 		if(l == r) 
		{
		 	sum[cnt] = a[l] % p;
		 	return;
		}
 		int mid = l + r >> 1;
 		build(cnt << 1, l, mid);
 		build(cnt << 1 | 1, mid + 1, r);
 		pushup(cnt);
	 }
 	void add1(int cnt, int l, int r, int nl, int nr, ll k)
 	{
 		if(l >= nl && r <= nr) 
 		{
 			sum[cnt] = (sum[cnt] + (r - l + 1) * k % p) % p;
 			lazy1[cnt] = (lazy1[cnt] + k % p) % p;
 			return;
		}
		int mid = l + r >> 1;
		pushdown(cnt, l, r);
		if(nl <= mid) add1(cnt << 1, l, mid, nl, nr, k);
		if(nr > mid) add1(cnt << 1 | 1, mid + 1, r, nl, nr, k);
		pushup(cnt);
	}
	void add2(int cnt, int l, int r, int nl, int nr, ll k)
 	{
 		if(l >= nl && r <= nr) 
 		{
 			sum[cnt] = sum[cnt] * k % p;
 			lazy1[cnt] = lazy1[cnt] * k % p;
 			lazy2[cnt] = lazy2[cnt] * k % p;
 			return;
		}
		int mid = l + r >> 1;
		pushdown(cnt, l, r);
		if(nl <= mid) add2(cnt << 1, l, mid, nl, nr, k);
		if(nr > mid) add2(cnt << 1 | 1, mid + 1, r, nl, nr, k);
		pushup(cnt);
	}
	ll query(int cnt, int l, int r, int nl, int nr)
	{
		if(l >= nl && r <= nr) return sum[cnt] % p;
		int mid = l + r >> 1;
		ll ans = 0;
		pushdown(cnt, l, r);
		if(nl <= mid) ans += query(cnt << 1, l, mid, nl, nr);
		if(nr > mid) ans += query(cnt << 1 | 1, mid + 1, r, nl, nr);
		return ans;
	}
}

int main()
{
	scanf("%d%d%d", &n, &m, &p);
	for(int i = 1; i <= n; i ++) a[i] = read();
	seg::build(1, 1, n);
	int opt, x, y;
	ll k, ans = 0;
	for(int i = 1; i <= m; i ++)
	{
		
		opt = read(), x = read(), y = read();
		if(opt == 1)
		{
			k = read();
			seg::add2(1, 1, n, x, y, k);
		}
		else if(opt == 2)
		{
			k = read();
			seg::add1(1, 1, n, x, y, k);
		}
		else if(opt == 3)
		{
			ans = seg::query(1, 1, n, x, y);
			printf("%lld
", ans % p);
		}
	}
}

树状数组1

#include<bits/stdc++.h>
using namespace std;
const int N = 500005;
typedef long long ll;
ll read()
{
	char c = getchar(), last = ' ';
	ll ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
int n, m;
ll a[N];
namespace bit
{
	ll s[N];
	int low(int x){return x & -x;}
	void add(int x, ll k){for(; x <= n; x += low(x)) s[x] += k;}
	ll query(int x){ll ans = 0; for(; x; x -= low(x)) ans += s[x]; return ans;}
}
int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i ++) bit::add(i, read());
	ll opt, x, y;
	for(int i = 1; i <= m; i ++)
	{
		opt = read(), x = read(), y = read();
		if(opt == 1) bit::add(x, y);
		else if(opt == 2) printf("%lld
", bit::query(y) - bit::query(x - 1));
	}
}

树状数组2

#include<bits/stdc++.h>
using namespace std;
const int N = 500005;
typedef long long ll;
ll read()
{
	char c = getchar(), last = ' ';
	ll ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
int n, m;
ll a[N];
namespace bit
{
	ll s[N];
	int low(int x){return x & -x;}
	void add(int x, ll k){for(; x <= n; x += low(x)) s[x] += k;}
	ll query(int x){ll ans = 0; for(; x; x -= low(x)) ans += s[x]; return ans;}
}
int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i ++) a[i] = read();
	ll opt, x, y, k;
	for(int i = 1; i <= m; i ++)
	{
		opt = read(), x = read();
		if(opt == 1)
		{
			y = read(), k = read();
			bit::add(x, k);
			bit::add(y + 1, -k);
		} 
		else if(opt == 2) printf("%lld
", bit::query(x) + a[x]);
	}
}

st表

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
{
	char c = getchar(), last = ' ';
	int ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
const int N = 100005;
int n, m;
int st[N][21], Log[N];
int find(int x, int y)
{
	int t = y - x + 1;
	return max(st[x][Log[t]], st[y - (1 << Log[t]) + 1][Log[t]]);
}
int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; (1 << i) < N; i ++) Log[1 << i] = i;
	for(int i = 1; i <= n; i ++) if(Log[i] == 0) Log[i] = Log[i - 1]; 
	for(int i = 1; i <= n; i ++) st[i][0] = read();
	for(int i = 1; (1 << i) <= N; i ++)
		for(int j = 1; (j + (1 << i - 1)) <= n; j ++)
			st[j][i] = max(st[j][i - 1], st[j + (1 << (i - 1))][i - 1]);
	for(int i = 1, x, y; i <= m; i ++)
	{
		x = read(), y = read();
		printf("%d
", find(x, y));
	}
	
}

单调队列(滑动窗口)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
{
	char c = getchar(), last = ' ';
	int ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
const int N = 1000005;
int n, k, a[N];
int q[N], l, r;
int main()
{
	n = read(), k =read();
	for(int i = 1; i <= n; i ++) a[i] = read();
	for(int i = 1; i <= n; i ++)
	{
		while(l <= r && i - q[l] + 1 > k) l ++;
		while(l <= r && a[q[r]] >= a[i]) r --;
		q[++r] = i;
		if(i >= k)
		printf("%d ", a[q[l]]);
	}
	printf("
");
	l = 0, r = 0;
	for(int i = 1; i <= n; i ++)
	{
		while(l <= r && i - q[l] + 1 > k) l ++;
		while(l <= r && a[q[r]] <= a[i]) r --;
		q[++r] = i;
		if(i >= k)
		printf("%d ", a[q[l]]);
	}
}

平衡树(fhq treap)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1100005;
int read()
{
	int ans = 0;
	char c = getchar(), last = ' ';
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = (ans << 1) + (ans << 3) + c - '0', c = getchar();
	if(last == '-') ans = - ans;
	return ans;
}
int ecnt;
struct tree
{
	int l, r, siz, rad, val;
}t[N<<2];
unsigned long long seed = 1;
int Rand()
{
	seed *= 260817;
	return int(seed);
}
void update(int cnt)
{
	t[cnt].siz = t[t[cnt].l].siz + t[t[cnt].r].siz + 1;
}

int New(int x)
{
	t[++ecnt].val = x;
	t[ecnt].rad = Rand();
	t[ecnt].siz = 1;
	return ecnt;
}

void split(int cnt, int k, int &x, int &y)
{
	if(!cnt)
	{
		x = y = 0;
		return;
	}
	if(t[cnt].val <= k)
	{
		x = cnt;
		split(t[cnt].r, k, t[cnt].r, y);
	}
	if(t[cnt].val > k)
	{
		y = cnt;
		split(t[cnt].l, k, x, t[cnt].l);
	}
	update(cnt);
}

int merge(int x, int y)
{
	if(x == 0) return y;
	if(y == 0) return x;
	if(t[x].rad <= t[y].rad)
	{
		t[x].r = merge(t[x].r, y);
		update(x);
		return x;
	}
	else if(t[x].rad > t[y].rad)
	{
		t[y].l = merge(x, t[y].l);
		update(y);
		return y;
	}
}

int kth(int cnt, int k)
{
	if(t[t[cnt].l].siz + 1 == k) return t[cnt].val;
	if(t[t[cnt].l].siz >= k) return kth(t[cnt].l, k);
	else return kth(t[cnt].r, k - t[t[cnt].l].siz - 1);
}

int n, m, rt;
int last = 0, ans = 0;

int main()
{
	//freopen("1.in", "r", stdin);
	//freopen("1.out", "w", stdout); 
	//srand(time(0));
	scanf("%d%d", &n, &m);
	int x, y, z, k, opt;
	for(int i = 1; i <= n; i ++)
	{
		k = read();
		split(rt, k, x, y);
		rt = merge(merge(x, New(k)), y);
	}
	for(int i = 1; i <= m; i ++)
	{
		opt = read(), k = read();
		k ^= last;
		if(opt == 1) 
		{
			split(rt, k, x, y);
			rt = merge(merge(x, New(k)), y);
		}
		if(opt == 2)
		{
			split(rt, k, x, y);
			split(x, k - 1, x, z);
			z = merge(t[z].l, t[z].r);
			rt = merge(merge(x, z), y); 
		}
		if(opt == 3)
		{
			split(rt, k - 1, x, y);
			last = t[x].siz + 1;
			ans ^= last;
			//printf("%lld
", last);
			rt = merge(x, y);
		}
		if(opt == 4)
		{
			last = kth(rt, k);
			ans ^= last;
			//printf("%lld
", last);
		}
		if(opt == 5)
		{
			split(rt, k - 1, x, y);
			last = kth(x, t[x].siz);
			ans ^= last;
			//printf("%lld
", last);
			rt = merge(x, y);
		}
		if(opt == 6)
		{
			split(rt, k, x, y);
			last = kth(y, 1);
			ans ^= last;
			//printf("%lld
", last);
			rt = merge(x, y);
		}
	}
	printf("%d", ans);
}

图论

最小生成树

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
{
	char c = getchar(), last = ' ';
	int ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
const int N = 5005, M = 200005;
int n, m, fa[N], ans;
int ecnt;
struct edge
{
	int to, dis, from;
}edg[M << 1];
int find(int x)
{
	while(x != fa[x]) x = fa[x] = fa[fa[x]];
	return x;
}
bool cmp(edge x, edge y)
{
	return x.dis < y.dis;
}
void kruscal()
{
	sort(edg + 1, edg + 1 + m, cmp);
	int cnt = 0;
	for(int i = 1; i <= m; i ++)
	{
		int u = edg[i].from, v = edg[i].to;
		if(find(u) == find(v)) continue;
		cnt ++;
		ans += edg[i].dis;
		fa[find(v)] = find(u);
		if(cnt == n - 1) break;
	}
}
int main()
{
	n = read(), m = read();
	for(int i = 1; i <= n; i ++) fa[i] = i;
	for(int i = 1; i <= m; i ++)
	{
		edg[++ecnt].from = read();
		edg[ecnt].to = read();
		edg[ecnt].dis = read();
	}
	kruscal();
	printf("%d", ans);
}

单源最短路(dijkstra)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
{
	char c = getchar(), last = ' ';
	int ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
const int N = 100005;
int head[N], ecnt;
struct edge
{
	int to, dis, nxt;
}edg[N << 2];
void add(int u, int v, int w)
{
	edg[++ecnt].to = v;
	edg[ecnt].dis = w;
	edg[ecnt].nxt = head[u];
	head[u] = ecnt;
}
int n, m, s;
int dis[N], vis[N];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
void dij()
{
	memset(dis, 0x3f, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	dis[s] = 0;
	q.push(make_pair(0, s));
	while(!q.empty())
	{
		int u = q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u] = 1;
		for(int i = head[u]; i; i = edg[i].nxt)
		{
			int v = edg[i].to;
			if(dis[v] > dis[u] + edg[i].dis)
			{
				dis[v] = dis[u] + edg[i].dis;
				q.push(make_pair(dis[v], v));
			}
		}
	}
}
int main()
{
	n = read(), m = read(), s = read();
	for(int i = 1, u, v, w; i <= m; i ++)
	{
		u = read(), v = read(), w = read();
		add(u, v, w);
	}
	dij();
	for(int i = 1; i <= n; i ++) printf("%d ", dis[i]);
}

单源最短路(SPFA)

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int ans=0;
	char last=' ',ch=getchar();
	while(ch<'0'||ch>'9') last=ch,ch=getchar();
	while(ch>='0'&&ch<='9') ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
	if(last=='-')ans=-ans;
	return ans;
}
const int N = 10005, M = 500005;
int head[N], ecnt;
struct edge
{
	int to, dis, nxt;
}edg[M];
void add(int u, int v, int w)
{
	edg[++ecnt].to = v;
	edg[ecnt].dis = w;
	edg[ecnt].nxt = head[u];
	head[u] = ecnt;
}
int n, m, s;
queue<int> q;
int dis[N], in[N];
void spfa()
{
	memset(dis, 0x3f, sizeof(dis));
	q.push(s);
	dis[s] = 0;
	in[s] = 1;
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		in[u] = 0;
		for(int i = head[u]; i; i = edg[i].nxt)
		{
			int v = edg[i].to;
			if(dis[v] > dis[u] + edg[i].dis)
			{
				dis[v] = dis[u] + edg[i].dis;
				if(!in[v]) q.push(v), in[v] = 1;
			}
		}
	}
}
int main()
{

	n = read(), m = read(), s = read();
	for(int i = 1, u, v, w; i <= m; i ++)
	{
		u = read(), v = read(), w = read();
		add(u, v, w);
	}
	spfa();
	for(int i = 1; i <= n; i ++) 
	{
		if(dis[i] == 0x3f3f3f3f) printf("%d ", (1 << 31) - 1);
		else printf("%d ", dis[i]);
	}
}

负环

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int ans=0;
	char last=' ',ch=getchar();
	while(ch<'0'||ch>'9') last=ch,ch=getchar();
	while(ch>='0'&&ch<='9') ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
	if(last=='-')ans=-ans;
	return ans;
}
const int N = 2005;
int head[N], ecnt;
struct edge
{
	int to, dis, nxt;
}edg[N << 2];
void add(int u, int v, int w)
{
	edg[++ecnt].to = v;
	edg[ecnt].dis = w;
	edg[ecnt].nxt = head[u];
	head[u] = ecnt;
}
int n, m;
queue<int> q;
int dis[N], vis[N], in[N];
bool spfa()
{
	memset(dis, 0x3f, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	memset(in, 0, sizeof(in));
	q.push(1);
	dis[1] = 0;
	in[1] = 1;
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		in[u] = 0;
		if(vis[u] == n - 1) return 1;
		vis[u] ++;
		for(int i = head[u]; i; i = edg[i].nxt)
		{
			int v = edg[i].to;
			if(dis[v] > dis[u] + edg[i].dis)
			{
				dis[v] = dis[u] + edg[i].dis;
				if(!in[v]) q.push(v), in[v] = 1;
			}
		}
	}
	return 0;
}
int t;
int main()
{
	t = read();
	while(t --)
	{
		ecnt = 0;
		memset(head, 0, sizeof(head));
		n = read(), m = read();
		for(int i = 1, u, v, w; i <= m; i ++)
		{
			u = read(), v = read(), w = read();
			if(w >= 0) add(u, v, w), add(v, u, w);
			else add(u, v, w);
		}
		if(spfa()) printf("YES
");
		else printf("NO
");
	}
	
}

差分约束

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int ans=0;
	char last=' ',ch=getchar();
	while(ch<'0'||ch>'9') last=ch,ch=getchar();
	while(ch>='0'&&ch<='9') ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
	if(last=='-')ans=-ans;
	return ans;
}
const int N = 100005;
int head[N], ecnt;
struct edge
{
	int to, dis, nxt;
}edg[N << 2];
void add(int u, int v, int w)
{
	edg[++ecnt].to = v;
	edg[ecnt].dis = w;
	edg[ecnt].nxt = head[u];
	head[u] = ecnt;
}
int n, m;
queue<int> q;
int dis[N], vis[N], in[N];
bool spfa()
{
	q.push(0);
	in[0] = 1;
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		in[u] = 0;
		if(vis[u] == n - 1) return 1;
		vis[u] ++;
		for(int i = head[u]; i; i = edg[i].nxt)
		{
			int v = edg[i].to;
			if(dis[v] < dis[u] + edg[i].dis)
			{
				dis[v] = dis[u] + edg[i].dis;
				if(!in[v]) q.push(v), in[v] = 1;
			}
		}
	}
	return 0;
}
int main()
{
	n = read(), m = read();
	for(int i = 1; i <= n; i ++) add(0, i, 1);
	for(int i = 1, u, v, w; i <= m; i ++)
	{
		u = read(), v = read(), w = read();
		add(u, v, -w);
	}
	if(spfa()) printf("NO");
	else for(int i = 1; i <= n; i ++) printf("%d ", dis[i]);
}

LCA(最近公共祖先)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
{
	char c = getchar(), last = ' ';
	int ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
const int N = 500005;
int head[N], ecnt;
struct edge
{
	int to, nxt;
}edg[N << 2];
void add(int u, int v)
{
	edg[++ecnt].to = v;
	edg[ecnt].nxt = head[u];
	head[u] = ecnt;
}
int n, m, s;
int fa[N][24], dep[N], cnt;
void dfs(int x, int f)
{
	for(int i = head[x]; i; i = edg[i].nxt)
	{
		int v = edg[i].to;
		if(v == f) continue;
		dep[v] = dep[x] + 1;
		fa[v][0] = x;
		dfs(v, x);
	}
}
int find(int x, int y)
{
	if(dep[x] < dep[y]) swap(x, y);
	int d = dep[x] - dep[y];
	for(int i = 22; i >= 0; i --)
	{
		if(d & (1 << i)) x = fa[x][i];
	}
	if(x == y) return x;
	for(int i = 22; i >= 0; i --)
	{
		if(fa[x][i] != fa[y][i]) 
		{
			x = fa[x][i]; 
			y = fa[y][i];
		}
	}
	return fa[x][0];
}
int main()
{
	n = read(), m = read(), s = read();
	for(int i = 1, x, y; i < n; i ++) 
	{
		x = read(), y = read();
		add(x, y);
		add(y, x);
	}
	dep[s] = 1;
	dfs(s, s);
	for(int i = 1; i <= 23; i ++) 
	{
		for(int j = 1; j <= n; j ++)
		{
			fa[j][i] = fa[fa[j][i - 1]][i - 1];
		}
	}
	for(int i = 1, x, y; i <= m; i ++)
	{
		x = read(), y = read();
		printf("%d
", find(x, y));
	}
}

树的直径(dfs)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
{
	char c = getchar(), last = ' ';
	int ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
const int N = 100005;
int head[N], ecnt;
struct edge
{
	int to, nxt, dis;
}edg[N << 2];
void add(int u, int v, int w)
{
	edg[++ecnt].to = v;
	edg[ecnt].dis = w;
	edg[ecnt].nxt = head[u];
	head[u] = ecnt;
}
int n, k, s, maxn;
int dis[N];
void dfs(int x, int fa)
{
	for(int i = head[x]; i; i = edg[i].nxt)
	{
		int v = edg[i].to;
		if(v == fa) continue;
		dis[v] = dis[x] + edg[i].dis;
		if(dis[v] > maxn) maxn = dis[v], s = v;
		dfs(v, x);
	}
}
int main()
{
	n = read();
	for(int i = 1, u, v, w; i < n; i ++)
	{
		u = read(), v = read(), w = read();
		add(u, v, w);
		add(v, u, w);
	}
	dis[1] = 0, maxn = 0;
	dfs(1, 1);
	dis[s] = 0, maxn = 0;
	dfs(s, s);
	printf("%d", maxn);
}

树的直径(dp)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
{
	char c = getchar(), last = ' ';
	int ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
const int N = 100005;
int head[N], ecnt;
struct edge
{
	int to, nxt, dis;
}edg[N << 2];
void add(int u, int v, int w)
{
	edg[++ecnt].to = v;
	edg[ecnt].dis = w;
	edg[ecnt].nxt = head[u];
	head[u] = ecnt;
}
int n, k, s, ans;
int f[N];
void dp(int x, int fa)
{
	for(int i = head[x]; i; i = edg[i].nxt)
	{
		int v = edg[i].to;
		if(v == fa) continue;
		dp(v, x);
		ans = max(ans, f[x] + edg[i].dis + f[v]);
		f[x] = max(f[x], f[v] + edg[i].dis);
	}
}
int main()
{
	n = read();
	for(int i = 1, u, v, w; i < n; i ++)
	{
		u = read(), v = read(), w = read();
		add(u, v, w);
		add(v, u, w);
	}
	dp(1, 0);
	printf("%d", ans);
}

缩点(tarjan)

#include<bits/stdc++.h>
using namespace std;
const int N = 10005, M = 100005;
int n, m;
int a[N];
int head[N], head1[N], ecnt, ecnt1;
struct edge
{
	int to, nxt;
}edg[M], edg1[M];
void add(int u, int v)
{
	edg[++ecnt].to = v;
	edg[ecnt].nxt = head[u];
	head[u] = ecnt;
}

namespace tar
{
	int low[N], dep[N], s[N], in[N], scc[N], val[N], top, cnt, ct;
	void tarjan(int x)
	{
		low[x] = dep[x] = ++cnt;
		s[top++] = x;
		in[x] = 1;
		for(int i = head[x]; i; i = edg[i].nxt)
		{
			int v = edg[i].to;
			if(!dep[v])
			{
				tarjan(v);
				low[x] = min(low[x], low[v]);
			}
			else if(in[v])
			{
				low[x] = min(low[x], dep[v]);
			}
		}
		if(low[x] == dep[x])
		{
			ct ++;
			while(s[top] != x)
			{
				top --;
				in[s[top]] = 0;
				scc[s[top]] = ct;
				val[ct] += a[s[top]];
			}
		}
	}
}

namespace top
{
	void add1(int u, int v)
	{
		edg1[++ecnt1].to = v;
		edg1[ecnt1].nxt = head1[u];
		head1[u] = ecnt1;
	}
	int in[N], f[N];
	void build()
	{
		for(int i = 1; i <= n; i ++)
		{
			for(int j = head[i]; j; j = edg[j].nxt)
			{
				int v = edg[j].to;
				if(tar::scc[i] != tar::scc[v])
				{
					add1(tar::scc[i], tar::scc[v]);
					in[tar::scc[v]] ++;
				}
			}
		}
	}
	int topo()
	{
		queue<int> q;
		for(int i = 1; i <= tar::ct; i ++) 
			if(in[i] == 0) q.push(i), f[i] = tar::val[i];
		while(!q.empty())
		{
			int u = q.front();
			q.pop();
			for(int i = head1[u]; i; i = edg1[i].nxt)
			{
				int v = edg1[i].to;
				f[v] = max(f[v], f[u] + tar::val[v]);
				in[v] --;
				if(in[v] == 0) q.push(v);
			}
		}
		int ans = 0;
		for(int i = 1; i <= tar::ct; i ++) ans = max(ans, f[i]);
		return ans;
	}
}

int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
	for(int i = 1, u, v; i <= m; i ++)
	{
		scanf("%d%d", &u, &v);
		add(u, v);
	}
	for(int i = 1; i <= n; i ++)
		if(!tar::dep[i]) tar::tarjan(i);
	top::build();
	printf("%d", top::topo());
}

次短路


数论

gcd

#include<bits/stdc++.h>
using namespace std;
int gcd(int a, int b)
{
	if(b == 0) return a;
	return gcd(b, a % b);
}
int m, n;
int main()
{
	scanf("%d%d", &n, &m);
	printf("%d", gcd(n, m));
}

exgcd

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read()
{
	char c = getchar(), last = ' ';
	ll ans = 0;
	while(c < '0' || c > '9') last = c, c = getchar();
	while(c >= '0' && c <= '9') ans = ans * 10 + c - '0', c = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
ll gcd(ll a, ll b)
{
	if(b == 0) return a;
	return gcd(b, a % b);
}
void exgcd(ll a, ll b, ll &x, ll &y)
{
	if(b == 0)
	{
		x = 1;
		y = 0;
		return;
	}
	ll p;
	exgcd(b, a % b, x, y);
	p = x;
	x = y;
	y = p - y * (a / b);
	return;
}
int t;
ll a, b, c, d;
int main()
{
	ll t = read();
	while(t --)
	{
		a = read(), b = read(), c = read();
		ll x = 0, y = 0, dx, dy, l, r, s;
		d = gcd(a, b);
		if(c % d != 0) 
		{
			printf("-1
");
			continue;
		}
		a /= d, b /= d, c /= d;
		exgcd(a, b, x, y);
		x *= c, y *= c;
		dx = b, dy = a;
		//printf("%lld %lld
", dx, dy);
		l = ll(double(ceil(1.0 * (-x + 1) / (1.0 * dx))));
		r = ll(double(floor(1.0 * (y - 1) / (1.0 * dy))));
		//l = ll((-x + 1) / dx);
		//r = ll((y - 1) / dy);
		if(l > r) 
		{
			printf("%lld %lld
", x + l * dx, y - r * dy);
		}
		else 
		{
			printf("%lld %lld %lld %lld %lld
", r - l + 1, x + l * dx, y - r * dy, x + r * dx, y - l * dy);
		}
	}
}

乘法逆元(递推)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3000005;
ll n, p;
ll inv[N];
int main()
{
	scanf("%lld%lld", &n, &p);
	inv[1] = 1;
	for(int i = 2; i <= n; i ++)
		inv[i] = ((-(p / i) * inv[p % i]) % p + p) % p;
	for(int i = 1; i <= n; i ++) printf("%lld
", inv[i]);
}

乘法逆元((a^{p-2})

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3000005;
ll n, p;
ll qpow(ll a, ll b)
{
	ll ans = 1;
	while(b)
	{
		if(b & 1) ans = ans * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return ans;
}
ll inv[N];
int main()
{
	scanf("%lld%lld", &n, &p);
	printf("%lld", qpow(n, p - 2));
}

裴蜀定理

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, ans;
int gcd(int a, int b)
{
	if(b == 0) return a;
	return gcd(b, a % b);
}
int main()
{
	scanf("%d", &n);
	scanf("%d", &ans);
	for(int i = 1, x; i < n; i ++)
	{
		scanf("%d", &x);
		ans = gcd(ans, abs(x));
	}
	printf("%d", ans);
}

矩阵快速幂

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 105;
const ll mod = 1e9 + 7;
ll n, k;
struct martix
{
	ll a[N][N];
	martix(){memset(a, 0, sizeof(a));}
	void clear()
	{
		for(int i = 1; i <= n; i ++) a[i][i] = 1;
	}
}m;
martix cheng(martix a, martix b)
{
	martix c;
	for(int k = 1; k <= n; k ++)
		for(int i = 1; i <= n; i ++)
			for(int j = 1; j <= n; j ++)
			c.a[i][j] = (c.a[i][j] + 1ll * a.a[i][k] * b.a[k][j] + mod % mod) % mod;
	return c;	
}
martix qpow(martix a, ll b)
{
	martix ans;
	ans.clear();
	while(b)
	{
		if(b & 1) ans = cheng(ans, a);
		a = cheng(a, a);
		b >>= 1;
	}
	return ans;
}
int main()
{
	scanf("%lld%lld", &n, &k);
	
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++)
			scanf("%lld", &m.a[i][j]);
	martix ans = qpow(m, k);
	for(int i = 1; i <= n; i ++)
	{
		for(int j = 1; j <= n; j ++) 
			printf("%lld ", ans.a[i][j]);
		printf("
");
	}
}

矩阵加速(数列)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 105;
const ll mod = 1e9 + 7;
ll n, k;
struct martix
{
	ll a[N][N];
	martix(){memset(a, 0, sizeof(a));}
	void clear()
	{
		for(int i = 1; i <= 3; i ++) a[i][i] = 1;
	}
}m, t;
martix cheng(martix a, martix b)
{
	martix c;
	for(int k = 1; k <= 3; k ++)
		for(int i = 1; i <= 3; i ++)
			for(int j = 1; j <= 3; j ++)
			c.a[i][j] = (c.a[i][j] + 1ll * a.a[i][k] * b.a[k][j] + mod % mod) % mod;
	return c;	
}
martix qpow(martix a, ll b)
{
	martix ans;
	ans.clear();
	while(b)
	{
		if(b & 1) ans = cheng(ans, a);
		a = cheng(a, a);
		b >>= 1;
	}
	return ans;
}
int T;
int main()
{
	scanf("%d", &T);
	while(T --)
	{
		scanf("%lld", &n);
		m.a[1][1] = m.a[1][2] = m.a[1][3] = 1;
		t.a[1][1] = t.a[1][2] = t.a[2][3] = t.a[3][1] = 1;
		t.a[1][3] = t.a[2][1] = t.a[2][2] = t.a[3][2] = t.a[3][3]= 0;
		martix ans = qpow(t, n - 1);
		martix qwq;
		for(int k = 1; k <= 3; k ++) 
			for(int i = 1; i <= 1; i ++)
				for(int j = 1; j <= 3; j ++)
					qwq.a[i][j] = (qwq.a[i][j] + (1ll * m.a[i][k] * ans.a[k][j] + mod) % mod) % mod;
		printf("%lld
", qwq.a[1][3]);
	}
	
}
原文地址:https://www.cnblogs.com/lcezych/p/13916100.html