首页 > 编程语言 >算法模板 v1.10.5.20240330

算法模板 v1.10.5.20240330

时间:2024-03-30 19:34:10浏览次数:27  
标签:node 5.20240330 return cur val int v1.10 void 模板

算法模板

v1.1.1.20240115:之前历史版本已不可寻,创建第一份算法模板。

v1.2.1.20240116:删除“编译”-“手动开栈”;删除“编译”-“手动开O优化”;修改“编译”-“CF模板”;删除“读写”;删除“图论”-“欧拉图”-“混合图”;删除“图论”-“可达性统计”;删除“数据类型”-“高精类”。

v1.3.1.20240120:恢复"读写"-"EMIO";删除“读写”-“EMIO”,代码转移至读写。

v1.3.2.20240124:修改“数据结构”-“并查集”;创建[toc]目录。

v1.4.1.20240128:创建“字符串”-“Z函数”。

v1.4.2.20240129:删除"编译"-"CF模板",代码转移至“编译”。

v1.5.1.20240130:创建"字符串"-"字典树"-”Trie“;创建"字符串"-"字典树"-”可持久化01Trie“;创建”随机化“-”模拟退火“。

v1.6.1.20240131:创建"图论"-”三元环计数“;修改”数据类型“-”大数类“。

v1.7.1.20240228:创建“表达式”-“获取优先级”;创建"表达式"-“中缀转后缀”;创建”表达式“-”建立表达式树“;修改“版本更新说明”。

v1.8.1.20240229:创建"字符串"-“Split”。

v1.9.1.20240303:创建"树论"-“K级祖先”。

v1.10.1.20240319:创建"枚举"-“排列”-“全排列”;创建"枚举"-“子集”-“枚举全部子集”;创建"枚举"-“子集”-“枚举k大小子集”。

v1.10.2.20240320:修改"数据结构"-“李超线段树”。

v1.10.3.20240323:修改“图论”-“网络流”-“最大流”-“Dinic”。

v1.10.4.20240325:修改"数据结构"-“可删堆”。

v1.10.5.20240330:修改"图论"-"网络流"-“最大流”-“Dinic”;修改"图论"-"网络流"-“费用流”-“ZKW费用流”。

目录

编译

#include<bits/stdc++.h>
using namespace std;
/*====================*/
#define endl "\n"
/*====================*/
typedef long long lnt;
/*====================*/
void Solve(void)
{

}
/*====================*/
int main()
{
#ifndef ONLINE_JUDGE
	freopen("IN.txt", "r+", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	int T = 1; //cin >> T;
	while (T--)Solve();
	return 0;
}

读写

namespace IO
{
	struct ENDL
	{
		//By ProtectEMmm
	}endl;
	class IStream
	{
	public:
		IStream& operator >>(int& temp)
		{
			temp = 0; char c = GetChar(); bool flag = false;
			while (isdigit(c) != true) { if (c == '-')flag = true; c = GetChar(); }
			while (isdigit(c) == true) { temp = temp * 10 + c - '0', c = GetChar(); }
			/*========================================*/temp = flag ? -temp : temp; return *this;
		}
		IStream& operator >>(char& temp)
		{
			temp = ' '; char c = GetChar();
			while (ischar(c) != true)c = GetChar();
			/*====================*/temp = c; return *this;
		}
		IStream& operator >>(double& temp)
		{
			temp = 0; char c = GetChar(); bool flag = false;
			while (isdigit(c) != true) { if (c == '-')flag = true; c = GetChar(); }
			while (isdigit(c) == true) { temp = temp * 10 + c - '0', c = GetChar(); }
			if (c == '.')
			{
				c = GetChar();
				double point = 0.1;
				while (isdigit(c) == true)
				{
					temp += point * (c - '0');
					point *= 0.1; c = GetChar();
				}
			}
			temp = flag ? -temp : temp;
			/*==========*/return *this;
		}
		IStream& operator >>(long long& temp)
		{
			temp = 0; char c = GetChar(); bool flag = false;
			while (isdigit(c) != true) { if (c == '-')flag = true; c = GetChar(); }
			while (isdigit(c) == true) { temp = temp * 10 + c - '0', c = GetChar(); }
			/*========================================*/temp = flag ? -temp : temp; return *this;
		}
		IStream& operator >>(std::string& temp)
		{
			temp.clear(); char c = GetChar();
			while (ischar(c) != true)c = GetChar();
			while (ischar(c) == true)temp += c, c = GetChar();
			/*========================================*/return *this;
		}
	private:
		char BUF[1 << 20] = { 0 };
		char* POS = BUF, * END = BUF;
		/*====================*/
		inline char GetChar(void)
		{
			if (POS == END)
			{
				END = (POS = BUF) + fread(BUF, 1, 1 << 20, stdin);
			}
			return POS == END ? EOF : *POS++;
		}
		inline bool ischar(const char& c)
		{
			return c != ' ' && c != '\n';
		}
		inline bool isdigit(const char& c)
		{
			return '0' <= c && c <= '9';
		}
	}cin;
	class OStream
	{
	public:
		~OStream(void)
		{
			Flush();
		}
		inline void Flush(void)
		{
			fwrite(BUF, 1, POS - BUF, stdout); POS = BUF;
		}
		inline void SetPoint(int x)
		{
			point = x;
		}
		OStream& operator <<(int temp)
		{
			int Top = 0; static int Stack[64];
			if (temp < 0) { PutChar('-'); temp = -temp; }
			do { Stack[Top++] = temp % 10; temp /= 10; } while (temp);
			while (Top) { PutChar(Stack[--Top] + '0'); } return *this;
		}
		OStream& operator <<(char temp)
		{
			PutChar(temp); return *this;
		}
		OStream& operator <<(ENDL temp)
		{
			PutChar('\n'); Flush(); return *this;
		}
		OStream& operator <<(double temp)
		{
			if (temp < 0)
			{
				PutChar('-');
				temp = -temp;
			}
			long long integer = temp;
			*this << integer;
			temp -= integer;
			PutChar('.');
			for (int i = 1; i <= point; ++i)
			{
				temp *= 10;
				PutChar(int(temp) + '0');
				temp -= int(temp);
			}
			return *this;
		}
		OStream& operator <<(long long temp)
		{
			int Top = 0; static int Stack[64];
			if (temp < 0) { PutChar('-'); temp = -temp; }
			do { Stack[Top++] = temp % 10; temp /= 10; } while (temp);
			while (Top) { PutChar(Stack[--Top] + '0'); } return *this;
		}
		OStream& operator <<(std::string temp)
		{
			for (auto c : temp)
			{
				PutChar(c);
			}
			return *this;
		}
		OStream& operator <<(const char temp[])
		{
			int p = 0;
			while (temp[p] != '\0')
			{
				PutChar(temp[p++]);
			}
			return *this;
		}
	private:
		int point = 6; char BUF[1 << 20] = { 0 };
		char* POS = BUF, * END = BUF + (1 << 20);
		/*====================*/
		inline void PutChar(char temp)
		{
			if (POS == END)
			{
				Flush();
			}
			*POS++ = temp;
		}
	}cout;
}
using namespace IO;

图论

存储

namespace _Graph
{
	const int N = 1e5 + 10;
	const int M = 1e5 + 10;
	/*====================*/
	struct Edge
	{
		int u, v, w;
		Edge(int _u = 0, int _v = 0, int _w = 0)
		{
			u = _u, v = _v, w = _w;
		}
		int node(int x)const
		{
			return x == u ? v : u;
		}
	};
	/*====================*/
	int n, m;
	Edge edge[M];
	vector<int>G[N];
	/*====================*/
	void Init(void)
	{
		cin >> n >> m;
        for (int i = 1; i <= n; ++i)
		{
			G[i].clear();
		}
		for (int i = 1; i <= m; ++i)
		{
			int u, v, w;
			cin >> u >> v >> w;
			edge[i] = Edge(u, v, w);
			G[u].push_back(i); G[v].push_back(i);
		}
	}
}

2-SAT

namespace _TwoSAT
{
	using namespace _SCC;
	void Init(void)
	{
		for (int i = 1; i <= n; ++i)
		{
			int u = idx[i][1], v = idx[i][0];
			if (belong[u] == belong[v])
			{
				cout << "IMPOSSIBLE" << endl; return;
			}
		}
		cout << "POSSIBLE" << endl;
		for (int i = 1; i <= n; ++i)
		{
			int u = idx[i][1], v = idx[i][0];
			cout << ((belong[u] < belong[v]) ? 1 : 0) << " ";
		}
		cout << endl;
	}
}

欧拉图

无向图

namespace _Euler
{
	/*
	默认连通图,-1不存在,0存在欧拉路径,1存在欧拉回路
	*/
	const int N = 1e5 + 10;
	/*====================*/
	int degree[N];
	/*====================*/
	int Init(void)
	{
		for (int i = 1; i <= n; ++i)
		{
			degree[i] = G[i].size();
		}
		int cnt = 0;
		for (int i = 1; i <= n; ++i)
		{
			if (degree[i] % 2 == 1)cnt++;
		}
		return cnt == 0 ? 1 : (cnt == 2 ? 0 : -1);
	}
}

有向图

namespace _Euler
{
	/*
	默认连通图,-1不存在,0存在欧拉路径,1存在欧拉回路
	*/
	const int N = 1e5 + 10;
	/*====================*/
	int degree[N];
	/*====================*/
	int Init(void)
	{
		for (int i = 1; i <= n; ++i)
		{
			degree[i] = 0;
		}
		for (int i = 1; i <= m; ++i)
		{
			int u = edge[i].u;
			int v = edge[i].v;
			degree[u]++, degree[v]--;
		}
		int cnt1 = 0, cnt2 = 0, cnt3 = 0;
		for (int i = 1; i <= n; ++i)
		{
			if (degree[i] == -1)cnt1++;
			if (degree[i] == +0)cnt2++;
			if (degree[i] == +1)cnt3++;
		}
		if (cnt1 == 1 && cnt3 == 1 && cnt2 + 2 == n)
		{
			return +0;
		}
		else if (cnt2 == n)
		{
			return +1;
		}
		else
		{
			return -1;
		}
	}
}

最大团

namespace _MaxClique
{
	const int N = 5e1 + 10;
	/*====================*/
	int n; int G[N][N];
	int dp[N], stk[N][N], res;
	/*====================*/
	bool DFS(int ns, int dep)
	{
		if (ns == 0)
		{
			if (dep > res)
			{
				res = dep; return true;
			}
			return false;
		}
		for (int i = 0; i < ns; ++i)
		{
			int u = stk[dep][i], cnt = 0;
			if (dep + dp[u] <= res)return false;
			if (dep + ns - i <= res)return false;
			for (int j = i + 1; j < ns; ++j)
			{
				int v = stk[dep][j];
				if (G[u][v])stk[dep + 1][cnt++] = v;
			}
			if (DFS(cnt, dep + 1))return true;
		}
		return false;
	}
	/*====================*/
	int Init(void)
	{
		cin >> n; res = 0;
		memset(dp, 0, sizeof(dp));
		for (int i = 1; i <= n; ++i)
		{
			for (int j = 1; j <= n; ++j)
			{
				cin >> G[i][j];
			}
		}
		for (int i = n; i >= 1; --i)
		{
			int ns = 0;
			for (int j = i + 1; j <= n; ++j)
			{
				if (G[i][j])stk[1][ns++] = j;
			}
			DFS(ns, 1); dp[i] = res;
		}
		return res;
	}
}

最短路

SPFA

namespace _SPFA
{
	const int N = 1e5 + 10;
	/*====================*/
	int dis[N]; bool vis[N];
	/*====================*/
	void Init(int s)
	{
		memset(dis, 0X3F, sizeof(dis));
		memset(vis, false, sizeof(vis));
		queue<int>q; dis[s] = 0; q.push(s);
		while (!q.empty())
		{
			int cur = q.front(); q.pop(); vis[cur] = false;
			for (int i = 0; i < G[cur].size(); ++i)
			{
				int val = edge[G[cur][i]].w;
				int nxt = edge[G[cur][i]].node(cur);
				if (dis[nxt] > dis[cur] + val)
				{
					dis[nxt] = dis[cur] + val;
					if (!vis[nxt])
					{
						q.push(nxt); vis[nxt] = true;
					}
				}
			}
		}
	}
}

Floyd

namespace _Floyd
{
	const int N = 2e2 + 10;
	/*====================*/
	int dp[N][N];
	/*====================*/
	void Init(void)
	{
		for (int k = 1; k <= n; ++k)
		{
			for (int i = 1; i <= n; ++i)
			{
				for (int j = 1; j <= n; ++j)
				{
					dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
				}
			}
		}
	}
}

Dijkstra

namespace _Dijkstra
{
	const int N = 1e5 + 10;
	/*====================*/
	struct Unit
	{
		int v, w;
		Unit(int _v = 0, int _w = 0)
		{
			v = _v, w = _w;
		}
		friend bool operator<(const Unit& a, const Unit& b)
		{
			return a.w > b.w;
		}
	};
	/*====================*/
	int dis[N]; bool vis[N];
	/*====================*/
	void Init(int s)
	{
		memset(dis, 0X3F, sizeof(dis));
		memset(vis, false, sizeof(vis));
		priority_queue<Unit>q;
		q.push(Unit(s, dis[s] = 0));
		while (!q.empty())
		{
			int cur = q.top().v; q.pop();
			if (vis[cur])continue; vis[cur] = true;
			for (int i = 0; i < G[cur].size(); ++i)
			{
				int val = edge[G[cur][i]].w;
				int nxt = edge[G[cur][i]].node(cur);
				if (dis[nxt] > dis[cur] + val)
				{
					dis[nxt] = dis[cur] + val;
					q.push(Unit(nxt, dis[nxt]));
				}
			}
		}
	}
}

SPFA-SLF

namespace _SPFA
{
	const int N = 1e5 + 10;
	/*====================*/
	int dis[N]; bool vis[N];
	/*====================*/
	void Init(int s)
	{
		memset(dis, 0X3F, sizeof(dis));
		memset(vis, false, sizeof(vis));
		deque<int>q; dis[s] = 0; q.push_back(s);
		while (!q.empty())
		{
			int cur = q.front();
			q.pop_front(); vis[cur] = false;
			if (!q.empty() && dis[q.front()] > dis[q.back()])
			{
				swap(q.front(), q.back());
			}
			for (int i = 0; i < G[cur].size(); ++i)
			{
				int val = edge[G[cur][i]].w;
				int nxt = edge[G[cur][i]].node(cur);
				if (dis[nxt] > dis[cur] + val)
				{
					dis[nxt] = dis[cur] + val;
					if (!vis[nxt])
					{
                        vis[nxt] = true;
						if (!q.empty() && dis[nxt] < dis[q.front()])
						{
							q.push_front(nxt);
						}
						else
						{
							q.push_back(nxt);
						}
					}
				}
			}
		}
	}
}

环相关

判环

namespace _Loop
{
	const int N = 1e5 + 10;
	/*====================*/
	int indegree[N];
	/*====================*/
	bool Init(void)
	{
		queue<int>q; int cnt = 0;
		memset(indegree, 0, sizeof(indegree));
		for (int i = 1; i <= m; ++i)
		{
			indegree[edge[i].v]++;
		}
		for (int i = 1; i <= n; ++i)
		{
			if (indegree[i] == 0)q.push(i);
		}
		while (!q.empty())
		{
			int cur = q.front(); q.pop(); cnt++;
			for (int i = 0; i < G[cur].size(); ++i)
			{
				int nxt = edge[G[cur][i]].node(cur);
				if (--indegree[nxt] == 0)q.push(nxt);
			}
		}
		return cnt == n;
	}
}

判负环

namespace _Loop
{
	const int N = 1e5 + 10;
	/*====================*/
	int dis[N], cnt[N]; bool vis[N];
	/*====================*/
	bool Init(void)
	{
		queue<int>q;
		memset(cnt, 0, sizeof(cnt));
		memset(dis, 0, sizeof(dis));
		for (int i = 1; i <= n; ++i)
		{
			q.push(i); vis[i] = true;
		}
		while (!q.empty())
		{
			int cur = q.front();
			q.pop(); vis[cur] = false;
			for (int i = 0; i < G[cur].size(); ++i)
			{
				int val = edge[G[cur][i]].w;
				int nxt = edge[G[cur][i]].node(cur);
				if (dis[nxt] > dis[cur] + val)
				{
					cnt[nxt] = cnt[cur] + 1;
					dis[nxt] = dis[cur] + val;
					if (cnt[nxt] > n)
					{
						return true;
					}
					if (!vis[nxt])
					{
						q.push(nxt); vis[nxt] = true;
					}
				}
			}
		}
		return false;
	}
}

求最小环

namespace _Loop
{
	int Init(void)
	{
		int res = 0X3F3F3F3F;
		for (int i = 1; i <= m; ++i)
		{
			_Dijkstra::Init(edge[i].v, i);
			res = min(res, dis[edge[i].u] + edge[i].w);
		}
		return res;
	}
}

网络流

最大流

ISAP
namespace _ISAP
{
	const int N = 1e5 + 10;
	const int M = 1e5 + 10;
	/*====================*/
	const int INF = 0X7FFFFFFF;
	/*====================*/
	struct Edge
	{
		int u, v, c, f;
		Edge(int _u = 0, int _v = 0, int _c = 0, int _f = 0)
		{
			u = _u, v = _v, c = _c, f = _f;
		}
	};
	/*====================*/
	int pre[N];//路径前驱
	int cur[N];//当前弧优化
	int n, m, s, t;//点,边,源,汇
	vector<int>G[N];//邻接表
	int d[N], vis[N], num[N];//图分层
	Edge edge[2 * M]; int cnt;//边
	/*====================*/
	void AddEdge(int u, int v, int c)
	{
		edge[cnt++] = Edge(u, v, c, 0);
		edge[cnt++] = Edge(v, u, 0, 0);
		G[u].push_back(cnt - 2);
		G[v].push_back(cnt - 1);
	}
	/*====================*/
	void BFS(void)
	{
		for (int i = 0; i <= n; ++i)
		{
			d[i] = vis[i] = num[i] = 0;
		}
		queue<int>q; q.push(t);
		d[t] = 0; vis[t] = 1;
		while (!q.empty())
		{
			int x = q.front(); q.pop();
			for (int i = 0; i < G[x].size(); ++i)
			{
				Edge& e = edge[G[x][i]];
				if (!vis[e.u] && e.c > e.f)
				{
					vis[e.u] = 1; d[e.u] = d[x] + 1; q.push(e.u);
				}
			}
		}
		for (int i = 0; i < n; ++i)num[d[i]]++;
	}
	int Augumemt(void)
	{
		int x, k = INF;
		x = t; while (x != s)
		{
			Edge& e = edge[pre[x]];
			k = min(k, e.c - e.f);
			x = edge[pre[x]].u;
		}
		x = t; while (x != s)
		{
			edge[pre[x]].f += k;
			edge[pre[x] ^ 1].f -= k;
			x = edge[pre[x]].u;
		}
		return k;
	}
	int MaxFlow(void)
	{
		for (int i = 1; i <= n; ++i)
		{
			pre[i] = cur[i] = 0;
		}

		BFS(); int x = s, flow = 0;
		
		while (d[s] < n)
		{
			if (x == t)
			{
				flow += Augumemt(); x = s;
			}
			int flag = 0;
			for (int& i = cur[x]; i < G[x].size(); ++i)
			{
				Edge& e = edge[G[x][i]];
				if (e.c > e.f && d[x] == d[e.v] + 1)
				{
					flag = 1; pre[e.v] = G[x][i]; x = e.v; break;
				}
			}
			if (!flag)
			{
				int l = n - 1;
				for (int i = 0; i < G[x].size(); ++i)
				{
					Edge& e = edge[G[x][i]];
					if (e.c > e.f)l = min(l, d[e.v]);
				}
				if (--num[d[x]] == 0)break;
				num[d[x] = l + 1]++; cur[x] = 0;
				if (x != s)x = edge[pre[x]].u;
			}
		}
		return flow;
	}
	/*====================*/
	int Init(void)
	{
		cnt = 0;
		cin >> n >> m >> s >> t;
		for (int i = 1; i <= n; ++i)
		{
			G[i].clear();
		}
		for (int i = 1; i <= m; ++i)
		{
			int u, v, c;
			cin >> u >> v >> c;
			AddEdge(u, v, c);
		}
		return MaxFlow();
	}
};
HLPP
namespace _HLPP
{
	const int N = 1e5 + 10;
	const int M = 1e5 + 10;
	/*====================*/
	const int INF = 0X7FFFFFFF;
	/*====================*/
	struct Edge
	{
		int next, v, c;
		Edge(int _next = 0, int _v = 0, int _c = 0)
		{
			next = _next, v = _v, c = _c;
		}
	};
	/*====================*/
	int n, m, s, t;
	int d[N], num[N];
	stack<int> lib[N];
	int ex[N], level = 0;
	Edge edge[2 * M]; int head[N], cnt;
	/*====================*/
	void AddEdge(int u, int v, int c) 
	{
		edge[cnt] = Edge(head[u], v, c), head[u] = cnt++;
		edge[cnt] = Edge(head[v], u, 0), head[v] = cnt++;
	}
	/*====================*/
	int Push(int u) 
	{
		bool init = u == s;
		for (int i = head[u]; i != -1; i = edge[i].next)
		{
			const int& v = edge[i].v, & c = edge[i].c;
			if (!c || init == false && d[u] != d[v] + 1)continue;
			int k = init ? c : min(c, ex[u]);
			if (v != s && v != t && !ex[v]) lib[d[v]].push(v), level = max(level, d[v]);
			ex[u] -= k, ex[v] += k, edge[i].c -= k, edge[i ^ 1].c += k;
			if (!ex[u]) return 0;
		}
		return 1;
	}
	void Relabel(int x) 
	{
		d[x] = INF;
		for (int i = head[x]; i != -1; i = edge[i].next)
		{
			if (edge[i].c) d[x] = min(d[x], d[edge[i].v]);
		}
		if (++d[x] < n) 
		{  
			lib[d[x]].push(x); level = max(level, d[x]); ++num[d[x]];
		}
	}
	bool BFS(void)
	{
		for (int i = 1; i <= n; ++i)
		{
			d[i] = INF; num[i] = 0;
		}
		queue<int>q; q.push(t), d[t] = 0;
		while (!q.empty()) 
		{
			int u = q.front(); q.pop(); num[d[u]]++;
			for (int i = head[u]; i!=-1; i = edge[i].next) 
			{
				const int& v = edge[i].v;
				if (edge[i ^ 1].c && d[v] > d[u] + 1) d[v] = d[u] + 1, q.push(v);
			}
		}
		return d[s] != INF;
	}
	int Select(void) 
	{
		while (lib[level].size() == 0 && level > -1) level--;
		return level == -1 ? 0 : lib[level].top();
	}
	int MaxFlow(void) 
	{
		if (!BFS()) return 0;
		d[s] = n; Push(s); int x;
		while (x = Select())
		{
			lib[level].pop();
			if (Push(x)) 
			{
				if (!--num[d[x]])
				{
					for (int i = 1; i <= n; ++i)
					{
						if (i != s && i != t && d[i] > d[x] && d[i] < n + 1)
						{
							d[i] = n + 1;
						}
					}
				}
				Relabel(x);
			}
		}
		return ex[t];
	}
	/*====================*/
	int Init(void)
	{
		cnt = 0;
		cin >> n >> m >> s >> t;
		memset(head, -1, sizeof(head));
		for (int i = 1; i <= m; ++i)
		{
			int u, v, c;
			cin >> u >> v >> c;
			AddEdge(u, v, c);
		}
		return MaxFlow();
	}
}
Dinic
/*
* 使用方法
* 1.创建对象
* 2.调用AddVertex()创建点
* 3.调用Init()初始化大小
* 4.调用AddEdge()创建边
* 5.调用MaxFlow()获取最大流
*/
class Max_Flow
{
public:
	static const int INF = 0X7FFFFFFF;
	/*====================*/
	struct Edge
	{
		int u, v, c, f;
		Edge(int _u = 0, int _v = 0, int _c = 0, int _f = 0)
		{
			u = _u, v = _v, c = _c, f = _f;
		}
	};
	/*====================*/
	int n = 2, s = 1, t = 2;
	/*====================*/
	vector<Edge>edge;
	vector<vector<int>>G;
private:
	vector<int>cur;//当前弧优化
	vector<int>d, vis;//图分层
	/*====================*/
	bool BFS(void)
	{
		fill(d.begin(), d.end(), 0);
		fill(vis.begin(), vis.end(), 0);
		d[s] = 0; vis[s] = 1;
		queue<int>q; q.push(s);
		while (!q.empty())
		{
			int x = q.front(); q.pop();
			for (int i = 0; i < G[x].size(); ++i)
			{
				Edge& e = edge[G[x][i]];
				if (!vis[e.v] && e.c > e.f)
				{
					vis[e.v] = 1; d[e.v] = d[x] + 1; q.push(e.v);
				}
			}
		}
		return vis[t];
	}
	int DFS(int x, int k)
	{
		int flow = 0, f;
		if (x == t || k == 0) return k;
		for (int& i = cur[x]; i < G[x].size(); ++i)
		{
			Edge& e = edge[G[x][i]];
			if (d[x] + 1 == d[e.v] && (f = DFS(e.v, min(k, e.c - e.f))) > 0)
			{
				e.f += f; edge[G[x][i] ^ 1].f -= f;
				flow += f; k -= f; if (k == 0) break;
			}
		}
		return flow;
	}
public:
	int S(void) { return s; }
	int T(void) { return t; }
	/*====================*/
	int AddVertex(void) 
	{ 
		return ++n; 
	}
	int AddEdge(int u, int v, int c)
	{
		edge.push_back(Edge(u, v, c, 0));
		edge.push_back(Edge(v, u, 0, 0));
		G[u].push_back(edge.size() - 2);
		G[v].push_back(edge.size() - 1);
		return edge.size() - 2;
	}
	/*====================*/
	void Init(void)
	{
		d.assign(n + 1, int());
		vis.assign(n + 1, int());
		cur.assign(n + 1, int());
		G.assign(n + 1, vector<int>());
	}
	/*====================*/
	int MaxFlow(void)
	{
		int flow = 0;
		while (BFS())
		{
			flow += DFS(s, INF);
			fill(cur.begin(), cur.end(), 0);
		}
		return flow;
	}
};
Dinic-Scaling
namespace _Dinic
{
	const int N = 1e5 + 10;
	const int M = 1e5 + 10;
	/*====================*/
	const int INF = 0X7FFFFFFF;
	/*====================*/
	struct Edge
	{
		int u, v, c, f;
		Edge(int _u = 0, int _v = 0, int _c = 0, int _f = 0)
		{
			u = _u, v = _v, c = _c, f = _f;
		}
		friend bool operator<(const Edge& a, const Edge& b)
		{
			return a.c > b.c;
		}
	};
	/*====================*/
	int d[N];//图分层
	int cur[N];//当前弧优化
	Edge _edge[M];//即将加入流网络的边
	int n, m, s, t;//点,边,源,汇
	vector<int>G[N];//邻接表
	Edge edge[2 * M]; int cnt;//边
	/*====================*/
	void AddEdge(int u, int v, int c)
	{
		edge[cnt++] = Edge(u, v, c, 0);
		edge[cnt++] = Edge(v, u, 0, 0);
		G[u].push_back(cnt - 2);
	}
	/*====================*/
	bool BFS(void)
	{
		for (int i = 0; i <= n; ++i)
		{
			d[i] = INF;
		}
		queue<int>q; q.push(s); d[s] = 0;
		while (!q.empty())
		{
			int x = q.front(); q.pop();
			for (int i = 0; i < G[x].size(); ++i)
			{
				Edge& e = edge[G[x][i]];
				if (d[e.v] >= INF && e.c > e.f)
				{
					d[e.v] = d[x] + 1; q.push(e.v);
				}
			}
		}
		return d[t] < INF;
	}
	int DFS(int x, int k)
	{
		int flow = 0, f;
		if (x == t || k == 0) return k;
		for (int& i = cur[x]; i < G[x].size(); ++i)
		{
			Edge& e = edge[G[x][i]];
			if (d[x] + 1 == d[e.v] && (f = DFS(e.v, min(k, e.c - e.f))) > 0)
			{
				e.f += f; edge[G[x][i] ^ 1].f -= f;
				flow += f; k -= f; if (k == 0) break;
			}
		}
		return flow;
	}
	int Dinic(void)
	{
		int flow = 0;
		while (BFS())
		{
			flow += DFS(s, INF);
			for (int i = 1; i <= n; ++i)
			{
				cur[i] = 0;
			}
		}
		return flow;
	}
	int MaxFlow(void)
	{
		int flow = 0;
		sort(_edge, _edge + m);
		for (int type : {0, 1})
		{
			for (int p = 1 << 30, i = 0; p; p /= 2)
			{
				while (i < m && _edge[i].c >= p)
				{
					if (type == 0)AddEdge(_edge[i].u, _edge[i].v, _edge[i].c);
					if (type == 1)G[_edge[i].v].push_back(i * 2 + 1); i++;
				}
				flow += Dinic();
			}
		}
		return flow;
	}
	/*====================*/
	int Init(void)
	{
		cnt = 0;
		cin >> n >> m >> s >> t;
		for (int i = 1; i <= n; ++i)
		{
			G[i].clear();
		}
		for (int i = 0; i < m; ++i)
		{
			int u, v, c;
			cin >> u >> v >> c;
			_edge[i] = Edge(u, v, c);
		}
		return MaxFlow();
	}
}

费用流

EK
namespace _EK
{
	const int N = 1e5 + 10;
	const int M = 1e5 + 10;
	/*====================*/
	const int INF = 0X3F3F3F3F;
	/*====================*/
	struct Edge
	{
		int next, v, c, w;
		Edge(int _next = 0, int _v = 0, int _c = 0, int _w = 0)
		{
			next = _next, v = _v, c = _c, w = _w;
		}
	};
	/*====================*/
	int n, m, s, t;
	int maxflow, mincost;
	Edge edge[2 * M]; int head[N], cnt;
	int dis[N], pre[N], incf[N]; bool vis[N];
	/*====================*/
	void AddEdge(int u, int v, int c, int w)
	{
		edge[cnt] = Edge(head[u], v, c, +w); head[u] = cnt++;
		edge[cnt] = Edge(head[v], u, 0, -w); head[v] = cnt++;
	}
	/*====================*/
	bool SPFA(void)
	{
		memset(dis, 0X3F, sizeof(dis));
		queue<int> q; q.push(s);
		dis[s] = 0, incf[s] = INF, incf[t] = 0;
		while (!q.empty())
		{
			int u = q.front(); q.pop(); vis[u] = false;
			for (int i = head[u]; i != -1; i = edge[i].next)
			{
				int v = edge[i].v, c = edge[i].c, w = edge[i].w;
				if (!c || dis[v] <= dis[u] + w) continue;
				dis[v] = dis[u] + w, incf[v] = min(c, incf[u]), pre[v] = i;
				if (!vis[v])q.push(v), vis[v] = true;
			}
		}
		return incf[t];
	}
	int MinCost(void)
	{
		while (SPFA())
		{
			maxflow += incf[t];
			for (int u = t; u != s; u = edge[pre[u] ^ 1].v)
			{
				edge[pre[u]].c -= incf[t];
				edge[pre[u] ^ 1].c += incf[t];
				mincost += incf[t] * edge[pre[u]].w;
			}
		}
		return mincost;
	}
	/*====================*/
	int Init(void)
	{
		cin >> n >> m >> s >> t;
		mincost = maxflow = cnt = 0;
		memset(head, -1, sizeof(head));
		for (int i = 1; i <= m; ++i)
		{
			int u, v, c, w;
			cin >> u >> v >> c >> w;
			AddEdge(u, v, c, w);
		}
		return MinCost();
	}
}
ZKW费用流
* 使用方法
* 1.创建对象
* 2.调用AddVertex()创建点
* 3.调用Init()初始化大小
* 4.调用AddEdge()创建边
* 5.调用MinCost()获取最小费用
*/
class Min_Cost
{
public:
	static const int INF = 0X7FFFFFFF;
	/*====================*/
	struct Edge
	{
		int u, v, c, w;
		Edge(int _u = 0, int _v = 0, int _c = 0, int _w = 0)
		{
			u = _u, v = _v, c = _c, w = _w;
		}
	};
	/*====================*/
	int n = 2, s = 1, t = 2;
	/*====================*/
	vector<Edge>edge;
	vector<vector<int>>G;
	int mincost, maxflow;
private:
	vector<int>dis;
	vector<bool>vis;
	/*====================*/
	bool SPFA(void)
	{
		fill(vis.begin(), vis.end(), false);
		fill(dis.begin(), dis.end(), INF);
		vis[t] = true, dis[t] = 0;
		deque<int> q; q.push_back(t);
		while (!q.empty())
		{
			int x = q.front(); q.pop_front(), vis[x] = false;
			if (!q.empty() && dis[q.front()] > dis[q.back()])
			{
				swap(q.front(), q.back());
			}
			for (int i = 0; i < G[x].size(); ++i)
			{
				Edge& e1 = edge[G[x][i] ^ 0];
				Edge& e2 = edge[G[x][i] ^ 1];
				if (e2.c != 0 && dis[e1.v] > dis[x] - e1.w)
				{
					dis[e1.v] = dis[x] - e1.w;
					if (!vis[e1.v])
					{
						vis[e1.v] = true;
						if (!q.empty() && dis[e1.v] < dis[q.front()])
						{
							q.push_front(e1.v);
						}
						else
						{
							q.push_back(e1.v);
						}
					}
				}
			}
		}
		return dis[s] < INF;
	}
	int DFS(int x, int k)
	{
		vis[x] = true; int flow = 0, f;
		if (x == t || k == 0) return k;
		for (int i = 0; i < G[x].size(); ++i)
		{
			Edge& e1 = edge[G[x][i] ^ 0];
			Edge& e2 = edge[G[x][i] ^ 1];
			if (vis[e1.v] || e1.c == 0)continue;
			if (dis[x] - e1.w == dis[e1.v] && (f = DFS(e1.v, min(k, e1.c))) > 0)
			{
				e1.c -= f, e2.c += f; flow += f, k -= f;
				mincost += f * e1.w; if (k == 0) break;
			}
		}
		return flow;
	}
public:
	/*====================*/
	int S(void) { return s; }
	int T(void) { return t; }
	/*====================*/
	int AddVertex(void)
	{
		return ++n;
	}
	int AddEdge(int u, int v, int c, int w)
	{
		edge.push_back(Edge(u, v, c, +w));
		edge.push_back(Edge(v, u, 0, -w));
		G[u].push_back(edge.size() - 2);
		G[v].push_back(edge.size() - 1);
		return edge.size() - 2;
	}
	/*====================*/
	void Init(void)
	{
		dis.assign(n + 1, int());
		vis.assign(n + 1, int());
		G.assign(n + 1, vector<int>());
	}
	/*====================*/
	int MinCost(void)
	{
		maxflow = mincost = 0;
		while (SPFA())
		{
			vis[t] = true;
			while (vis[t])
			{
				fill(vis.begin(), vis.end(), false);
				maxflow += DFS(s, INF);
			}
		}
		return mincost;
	}
};

支配树

namespace Lengauer_Tarjan
{
	struct Edge
	{
		int v, x;
		Edge(int _v = 0, int _x = 0)
		{
			v = _v, x = _x;
		}
	};
	/*====================*/
	int n, m;
	Edge edge[M * 3]; int head[3][N], tot;
	int idx[N], dfn[N], dfc;
	int fa[N], fth[N], mn[N], idm[N], sdm[N];
	/*====================*/
	void Add(int x, int u, int v)
	{
		edge[head[x][u] = ++tot] = Edge(v, head[x][u]);
	}
	void Add(int u, int v)
	{
		Add(0, u, v); Add(1, v, u);
	}
	void DFS(int u)
	{
		idx[dfn[u] = ++dfc] = u;
		for (int i = head[0][u]; i; i = edge[i].x)
		{
			int v = edge[i].v;
			if (!dfn[v])
			{
				DFS(v), fth[v] = u;
			}
		}
	}
	int Find(int x)
	{
		if (fa[x] == x)
		{
			return x;
		}
		int tmp = fa[x];
		fa[x] = Find(fa[x]);
		if (dfn[sdm[mn[tmp]]] < dfn[sdm[mn[x]]])
		{
			mn[x] = mn[tmp];
		}
		return fa[x];
	}
	void Tarjan(int st)
	{
		DFS(st);
		for (int i = 1; i <= n; ++i)
		{
			fa[i] = sdm[i] = mn[i] = i;
		}
		for (int i = dfc; i >= 2; --i)
		{
			int u = idx[i], res = INF;
			for (int j = head[1][u]; j; j = edge[j].x)
			{
				int v = edge[j].v; Find(v);
				if (dfn[v] < dfn[u])
				{
					res = min(res, dfn[v]);
				}
				else
				{
					res = min(res, dfn[sdm[mn[v]]]);
				}
			}
			sdm[u] = idx[res];
			fa[u] = fth[u];
			Add(2, sdm[u], u);
			u = fth[u];
			for (int j = head[2][u]; j; j = edge[j].x)
			{
				int v = edge[j].v; Find(v);
				if (sdm[mn[v]] == u)
				{
					idm[v] = u;
				}
				else
				{
					idm[v] = mn[v];
				}
			}
			head[2][u] = 0;
		}
		for (int i = 2; i <= dfc; ++i)
		{
			int u = idx[i];
			if (idm[u] != sdm[u])
			{
				idm[u] = idm[idm[u]];
			}
		}
	}
	/*====================*/
	void Init(int s)
	{
		Tarjan(s);
		tot = dfc = 0;
		for (int i = 1; i <= n; ++i)
		{
			dfn[i] = head[0][i] = head[1][i] = head[2][i] = 0;
		}
	}
	//树上连边idm[i] -> i;
}

拓扑排序

namespace _TopSort
{
    const int N = 1e5 + 10;
	/*====================*/
	int indegree[N];
	/*====================*/
	void Init(void)
	{
		queue<int>q;
		memset(indegree, 0, sizeof(indegree));
		for (int i = 1; i <= m; ++i)
		{
			indegree[edge[i].v]++;
		}
		for (int i = 1; i <= n; ++i)
		{
			if (indegree[i] == 0)q.push(i);
		}
		while (!q.empty())
		{
			int cur = q.front(); q.pop(); cout << cur << " ";
			for (int i = 0; i < G[cur].size(); ++i)
			{
				int nxt = edge[G[cur][i]].node(cur);
				if (--indegree[nxt] == 0)q.push(nxt);
			}
		}
	}
}

差分约束

namespace _SDC
{
    /*
    存在负环时无解
    记得建立一个超级源点
    A-B<=W的不等式,由B->A,边权为W
    跑最短路时为最大差值,跑最长路时为最小差值
    */
    const int N = 1e5 + 10;
	/*====================*/
	const int INF = 0X3F3F3F3F;
	/*====================*/
	int dis[N]; int cnt[N]; bool vis[N];
	/*====================*/
	bool Init(void)
	{
		G[0].clear(); cnt[0] = 0;
		for (int i = 1; i <= n; ++i)
		{
			G[0].push_back(++m);
			edge[m] = Edge(0, i, 0);
			dis[i] = INF, vis[i] = false, cnt[i] = 0;
		}
		queue<int>q; dis[0] = 0; q.push(0);
		while (!q.empty())
		{
			int cur = q.front(); q.pop(); vis[cur] = false;
			for (int i = 0; i < G[cur].size(); ++i)
			{
				int val = edge[G[cur][i]].w;
				int nxt = edge[G[cur][i]].node(cur);
				if (dis[nxt] > dis[cur] + val)
				{
					cnt[nxt] = cnt[cur] + 1;
					dis[nxt] = dis[cur] + val;
					if (cnt[nxt] > n)return false;
					if (!vis[nxt])
					{
						q.push(nxt); vis[nxt] = true;
					}
				}
			}
		}
		return true;
	}
}

图的连通性

双连通分量

边双连通分量
namespace _E_DCC
{
	const int N = 1e5 + 10;
	/*====================*/
	int belong[N], cnt;
	int dfn[N], low[N], num;
	/*====================*/
	void Tarjan(int cur, int in_edge)
	{
		dfn[cur] = low[cur] = ++num;
		for (int i = 0; i < G[cur].size(); ++i)
		{
			int nxt = edge[G[cur][i]].node(cur);
			if (!dfn[nxt])
			{
				Tarjan(nxt, G[cur][i]);
				low[cur] = min(low[cur], low[nxt]);
				if (low[nxt] > dfn[cur])
				{
					edge[G[cur][i]].bridge = true;
				}
			}
			else if (i != in_edge)
			{
				low[cur] = min(low[cur], dfn[nxt]);
			}
		}
	}
	void DFS(int cur)
	{
		belong[cur] = cnt;
		for (int i = 0; i < G[cur].size(); ++i)
		{
			int nxt = edge[G[cur][i]].node(cur);
			if (edge[G[cur][i]].bridge)continue;
			if (belong[nxt])continue; DFS(nxt);
		}
	}
	/*====================*/
	void Init(void)
	{
		for (int i = 1; i <= n; ++i)
		{
			if (!dfn[i])Tarjan(i, 0);
		}
		for (int i = 1; i <= n; ++i)
		{
			if (!belong[i])cnt++, DFS(i);
		}
	}
}
点双连通分量
namespace _V_DCC
{
	const int N = 1e5 + 10;
	/*====================*/
	vector<int>dcc[N];
	bool cut[N]; int cnt;
	stack<int>lib; int root;
	int dfn[N], low[N], num;
	/*====================*/
	void Tarjan(int cur)
	{
		int flag = 0; lib.push(cur);
		dfn[cur] = low[cur] = ++num;
		if (cur == root && G[cur].size() == 0)
		{
			dcc[++cnt].push_back(cur); return;
		}
		for (int i = 0; i < G[cur].size(); ++i)
		{
			int nxt = edge[G[cur][i]].node(cur);
			if (!dfn[nxt])
			{
				Tarjan(nxt);
				low[cur] = min(low[cur], low[nxt]);
				if (low[nxt] >= dfn[cur])
				{
					flag++; cnt++; int top;
					if (cur != root || flag > 1)
					{
						cut[cur] = true;
					}
					do
					{
						top = lib.top(); lib.pop();
						dcc[cnt].push_back(top);
					} while (top != nxt);
					dcc[cnt].push_back(cur);
				}
			}
			else
			{
				low[cur] = min(low[cur], dfn[nxt]);
			}
		}
	}
	/*====================*/
	void Init(void)
	{
		for (int i = 1; i <= n; ++i)
		{
			if (!dfn[i])Tarjan(root = i);
		}
	}
}
获取点双内部的边
void Tarjan(int cur, int e)
{
	dfn[cur] = low[cur] = ++num;
	if (cur != root || G[cur].size() != 0)
	{
		for (int i = 0; i < G[cur].size(); ++i)
		{
			int nxt = edge[G[cur][i]].node(cur);
			if (!dfn[nxt])
			{
				lib.push(G[cur][i]); Tarjan(nxt, G[cur][i]);
				low[cur] = min(low[cur], low[nxt]);
				if (low[nxt] >= dfn[cur])
				{
					cnt++; int top;
					do
					{
						top = lib.top(); lib.pop();
						dcc[cnt].push_back(edge[top].w);
					} while (top != G[cur][i]);
				}
			}
			else
			{
				if (dfn[nxt] < dfn[cur] && G[cur][i] != e)
				{
					lib.push(G[cur][i]);
				}
				low[cur] = min(low[cur], dfn[nxt]);
			}
		}
	}
}

强连通分量

namespace _SCC
{
	const int N = 1e5 + 10;
	/*====================*/
	int belong[N];
	int dfn[N], low[N], num;
	stack<int>lib; int ins[N];
	vector<int>scc[N]; int cnt;
	/*====================*/
	void Tarjan(int cur)
	{
		lib.push(cur); ins[cur] = 1;
		dfn[cur] = low[cur] = ++num;
		for (int i = 0; i < G[cur].size(); ++i)
		{
			int nxt = edge[G[cur][i]].node(cur);
			if (!dfn[nxt])
			{
				Tarjan(nxt);
				low[cur] = min(low[cur], low[nxt]);
			}
			else if (ins[nxt])
			{
				low[cur] = min(low[cur], dfn[nxt]);
			}
		}
		if (dfn[cur] == low[cur])
		{
			cnt++; int top;
			do
			{
				top = lib.top(); lib.pop(); ins[top] = 0;
				belong[top] = cnt; scc[cnt].push_back(top);
			} while (top != cur);
		}
	}
	/*====================*/
	void Init(void)
	{
        num = cnt = 0;
		for (int i = 1; i <= n; ++i)
		{
			dfn[i] = low[i] = 0;
		}
		for (int i = 1; i <= n; ++i)
		{
			if (!dfn[i])Tarjan(i);
		}
	}
}

最小树形图

有向有环图

挖坑:朱刘算法

有向无环图

namespace _DMST
{
	const int N = 1e5 + 10;
    /*====================*/
	const int INF = 0X7FFFFFFF;
	/*====================*/
	int val[N], sum;
	/*====================*/
	void Init(void)
	{
		sum = 0;
		for (int i = 1; i <= n; ++i)
		{
			val[i] = INF;
		}
		for (int i = 1; i <= m; ++i)
		{
			int u = edge[i].u;
			int v = edge[i].v;
			int w = edge[i].w;
			val[v] = min(val[v], w);
		}
		for (int i = 1; i <= n; ++i)
		{
			if (val[i] != INF)
			{
				sum += val[i];
			}
		}
	}
}

三元环计数

const int N = 1e5 + 10;
const int M = 2e5 + 10;
/*====================*/
int n, m;
struct Edge
{
	int u, v;
	Edge(int _u = 0, int _v = 0)
	{
		u = _u, v = _v;
	}
};
Edge edge[M];
int degree[N];
vector<int>Out[N];
/*====================*/
int tag[N];
/*====================*/
void Solve(void)
{
	cin >> n >> m;
	for (int i = 1; i <= m; ++i)
	{
		int u, v; 
		cin >> u >> v; 
		edge[i] = Edge(u, v);
		degree[u]++, degree[v]++;
	}
	for (int i = 1; i <= m; ++i)
	{
		int u = edge[i].u, v = edge[i].v;
		if (degree[u] == degree[v] && u > v)swap(u, v);
		if (degree[u] != degree[v] && degree[u] > degree[v])swap(u, v);
		Out[u].push_back(v);
	}
	int ans = 0;
	for (int u = 1; u <= n; ++u)
	{
		for (auto v : Out[u])
		{
			tag[v] = u;
		}
		for (auto v : Out[u])
		{
			for (auto w : Out[v])
			{
				if (tag[w] == u)
				{
					ans++;
				}
			}
		}
	}
	cout << ans << endl;
}

树论

LCT

class Link_Cut_Tree
{
public:
	void Init(void)
	{
		
	}
private:
	int rev[N], fa[N], ch[N][2];
	/*====================*/
	bool Which(int x)
	{
		return ch[fa[x]][1] == x;
	}
	bool IsRoot(int x)
	{
		return ch[fa[x]][Which(x)] != x;
	}
	/*====================*/
	void PushUp(int x)
	{
		/*PushUp*/
	}
	void PushAll(int x)
	{
		if (!IsRoot(x))
		{
			PushAll(fa[x]);
		}
		PushDown(x);
	}
	void PushDown(int x)
	{
		if (rev[x])
		{
			swap(ch[x][0], ch[x][1]);
			rev[ch[x][0]] ^= 1;
			rev[ch[x][1]] ^= 1;
			rev[x] = 0;
		}
		/*PushDown*/
	}
	/*====================*/
	void Rotate(int x)
	{
		int y = fa[x], z = fa[y], w = Which(x);
		if (!IsRoot(y)) ch[z][Which(y)] = x; fa[x] = z;
		ch[y][w] = ch[x][w ^ 1];
		if (ch[y][w]) fa[ch[y][w]] = y;
		ch[x][w ^ 1] = y; fa[y] = x;
		PushUp(y); PushUp(x);
	}
	void Splay(int x)
	{
		PushAll(x);
		for (; !IsRoot(x); Rotate(x))
		{
			if (!IsRoot(fa[x]))
			{
				Rotate(Which(x) == Which(fa[x]) ? fa[x] : x);
			}
		}
	}
	/*====================*/
	void Access(int x)
	{
		for (int p = 0; x; p = x, x = fa[x])
		{
			Splay(x), ch[x][1] = p, PushUp(x);
		}
	}
	/*====================*/
	int FindRoot(int x)
	{
		Access(x); Splay(x);
		while (ch[x][0]) x = ch[x][0];
		Splay(x); return x;
	}
	void MakeRoot(int x)
	{
		Access(x); Splay(x); rev[x] ^= 1;
	}
	/*====================*/
	void Cut(int u, int v)
	{
		Split(u, v);
		if (fa[u] == v && !ch[u][1])
		{
			ch[v][0] = fa[u] = 0;
		}
	}
	void Link(int u, int v)
	{
		MakeRoot(u); fa[u] = v;
	}
	/*====================*/
	void Split(int u, int v)
	{
		MakeRoot(u); Access(v); Splay(v);
	}
    /*====================*/
	int LCA(int u, int v)
	{
		Access(u); int ans = 0;
		for (int child = 0; v; child = v, v = fa[v])
		{
			Splay(v); ch[v][1] = child; ans = v;
		}
		return ans;
	}
}LCT;

LCA

树剖法

class _LCA
{
public:
	~_LCA(void)
	{
		delete[] node;
	}
	int operator()(int u, int v)
	{
		while (node[u].top != node[v].top)
		{
			int topu = node[u].top;
			int topv = node[v].top;
			if (node[topu].dep > node[topv].dep)
			{
				u = node[topu].pre;
			}
			else
			{
				v = node[topv].pre;
			}
		}
		return node[u].dep > node[v].dep ? v : u;
	}
	void init(int n, vector<int>G[], int root = 1)
	{
		this->G = G;
		this->root = root;
		node = new Node[n + 1];
		DFS1(root, root); DFS2(root, root);
	}
private:
	struct Node
	{
		int pre = -1;
		int dep = +0;
		int siz = +1;
		int son = -1;
		int top = -1;
	};
	/*====================*/
	int root = -1;
	Node* node = NULL;
	vector<int>* G = NULL;
	/*====================*/
	void DFS1(int pre, int cur)
	{
		node[cur].pre = pre;
		node[cur].dep = node[pre].dep + 1;
		for (auto nxt : G[cur])
		{
			if (nxt != pre)
			{
				DFS1(cur, nxt);
				node[cur].siz += node[nxt].siz;
				if (node[cur].son == -1)
				{
					node[cur].son = nxt;
				}
				else if (node[nxt].siz > node[node[cur].son].siz)
				{
					node[cur].son = nxt;
				}
			}
		}
	}
	void DFS2(int cur, int top)
	{
		node[cur].top = top;
		if (node[cur].son != -1)
		{
			DFS2(node[cur].son, top);
			for (auto nxt : G[cur])
			{
				if (nxt == node[cur].pre)continue;
				if (nxt == node[cur].son)continue;
				DFS2(nxt, nxt);
			}
		}
	}
};

ST表法

class _LCA
{
public:
	int operator()(int u, int v)
	{
		if (u == v)return u;
		if ((u = dfn[u]) > (v = dfn[v]))swap(u, v);
		int d = log2[v - u++];
		return Get(st[d][u], st[d][v - (1 << d) + 1]);
	}
	void init(int n, vector<int>G[], int root = 1)
	{
		this->G = G; dfn[0] = 0;
		/*====================*/
		log2[0] = -1;
		for (int i = 1; i <= n; ++i)
		{
			log2[i] = log2[i >> 1] + 1;
		}
		/*====================*/
		DFS(0, root);
		for (int i = 1; i <= log2[n]; i++)
		{
			for (int j = 1; j + (1 << i) - 1 <= n; j++)
			{
				st[i][j] = Get(st[i - 1][j], st[i - 1][j + (1 << i - 1)]);
			}
		}
	}
private:
	int dfn[N];
	int log2[N];
	int st[19][N];
	vector<int>* G;
	/*====================*/
	void DFS(int pre, int cur)
	{
		st[0][dfn[cur] = ++dfn[0]] = pre;
		for (auto nxt : G[cur])
		{
			if (nxt != pre)
			{
				DFS(cur, nxt);
			}
		}
	}
	int Get(int x, int y)
	{
		return dfn[x] < dfn[y] ? x : y;
	}
}lca;

树哈希

class Tree_Hash
{
public:
	int operator()(vector<int>G[], int root)
	{
		this->G = G;
		return DFS(root, root);
	}
private:
	vector<int>* G = NULL;
	map<vector<int>, int>mp;
	int DFS(int pre, int cur)
	{
		vector<int>vec;
		for (auto nxt : G[cur])
		{
			if (nxt != pre)
			{
				vec.push_back(DFS(cur, nxt));
			}
		}
		sort(vec.begin(), vec.end());
		if (mp.find(vec) == mp.end())
		{
			mp[vec] = mp.size();
		}
		return mp[vec];
	}
};

树分治

点分治

class _TCD
{
public:
	~_TCD(void)
	{
		delete[] siz;
		delete[] rooted;
	}
	void init(int n, vector<int>G[])
	{
		this->G = G;
		siz = new int[n + 10];
		rooted = new bool[n + 10];
		for (int i = 0; i < n + 10; ++i)
		{
			siz[i] = 0, rooted[i] = false;
		}
		DividTree(Centroid(1, n));
	}
private:
	vector<int>* G = NULL;
	/*====================*/
	int* siz = NULL;
	bool* rooted = NULL;
	/*====================*/
	int centroid, all_part;
	/*====================*/
	int Centroid(int cur, int all)
	{
		centroid = -1; all_part = all;
		DFS(cur, cur, all); return centroid;
	}
	void DFS(int pre, int cur, int all)
	{
		siz[cur] = 1; int cur_part = 0;
		for (int i = 0; i < G[cur].size(); ++i)
		{
			int nxt = G[cur][i];
			if (nxt == pre)continue;
			if (rooted[nxt])continue;
			DFS(cur, nxt, all);
			siz[cur] += siz[nxt];
			cur_part = max(cur_part, siz[nxt]);
		}
		cur_part = max(cur_part, all - siz[cur]);
		if (cur_part < all_part)
		{
			all_part = cur_part, centroid = cur;
		}
	}
	/*====================*/
	void CalcSon(int pre, int cur)
	{
		/*
			添加cur到右树tree中
		*/
		for (int i = 0; i < G[cur].size(); ++i)
		{
			int nxt = G[cur][i];
			if (nxt == pre)continue;
			if (rooted[nxt])continue;
			/*=====================*/
			CalcSon(cur, nxt);
		}
	}
	void CalcRoot(int root)
	{
		/*
			初始化左库lib
		*/
		for (int i = 0; i < G[root].size(); ++i)
		{
			int son = G[root][i];
			if (!rooted[son])
			{
				/*
					初始化右树tree
				*/
				CalcSon(son, son);
				/*
					遍历右树tree匹配左库lib
				*/
				/*
					添加右树tree到左库lib
				*/
			}
		}
	}
	/*====================*/
	void DividTree(int root)
	{
		rooted[root] = true; CalcRoot(root);
		for (int i = 0; i < G[root].size(); ++i)
		{
			int son = G[root][i];
			if (!rooted[son])
			{
				DividTree(Centroid(son, siz[son]));
			}
		}
	}
};

K级祖先

int topm = node[m].top;
while (t > 0)
{
	topm = node[m].top;
	if (node[m].dep - node[topm].dep < t)
	{
		t -= node[m].dep - node[topm].dep + 1;
		m = node[topm].pre;
	}
	else
	{
		m = node[node[m].dfn - t].idx; t = 0;
	}
}

树链剖分

重链剖分

struct Node
{
	int pre, dep, siz, son;
	int top, dfn, idx;
	int val;
	Node(void)
	{
		pre = -1; dep = +0;
		siz = +1; son = -1;
		top = -1; dfn = +0;
		idx = +0; val = +0;
	}
};
/*====================*/
Node node[N];
/*====================*/
class HLD
{
public:
	void operator()(vector<int>G[], int root = 1)
	{
        cnt = 0;
		this->G = G; this->root = root;
		DFS1(root, root); DFS2(root, root);
	}
private:
	int cnt = 0;
	int root = -1;
	vector<int>* G = NULL;
	/*====================*/
	void DFS1(int pre, int cur)
	{
		node[cur].pre = pre;
		node[cur].dep = node[pre].dep + 1;
		for (int i = 0; i < G[cur].size(); ++i)
		{
			int nxt = G[cur][i];
			if (nxt != pre)
			{
				DFS1(cur, nxt); node[cur].siz += node[nxt].siz;
				if (node[cur].son == -1)
				{
					node[cur].son = nxt;
				}
				else if (node[nxt].siz > node[node[cur].son].siz)
				{
					node[cur].son = nxt;
				}
			}
		}
	}
	void DFS2(int cur, int top)
	{
		node[cur].top = top;
		node[cur].dfn = ++cnt;
		node[cnt].idx = cur;
		if (node[cur].son != -1)
		{
			DFS2(node[cur].son, top);
			for (int i = 0; i < G[cur].size(); ++i)
			{
				int nxt = G[cur][i];
				if (nxt == node[cur].pre)continue;
				if (nxt == node[cur].son)continue;
				DFS2(nxt, nxt);
			}
		}
	}
};

树的重心

class Centroid
{
public:
	int operator()(int n, vector<int>G[])
	{
		this->G = G;
		siz = new int[n + 1];
		centroid = -1;
		all_part = n;
		DFS(1, 1, n);
		delete[] siz;
		return centroid;
	}
private:
	int* siz = NULL;
	int all_part = 0;
	int centroid = -1;
	vector<int>* G = NULL;
	/*====================*/
	void DFS(int pre, int cur, int all)
	{
		siz[cur] = 1;
		int cur_part = 0;
		for (auto nxt : G[cur])
		{
			if (nxt != pre)
			{
				DFS(cur, nxt, all);
				siz[cur] += siz[nxt];
				cur_part = max(cur_part, siz[nxt]);
			}
		}
		cur_part = max(cur_part, all - siz[cur]);
		if (cur_part < all_part)
		{
			all_part = cur_part, centroid = cur;
		}
	}
};

树上路径求交

假设当前要求路径 \((a,b)\) 和 \((c,d)\) 的交。
设 \(d_x\) 表示 \(x\) 的深度。
先求出 \(p[4]={lca(a,c),lca(a,d),lca(b,c),lca(b,d)}\)。
将 \(p\) 数组按深度排序,取出深度较大的两个,记为 \(p0,p1\)。
若存在交,则 \((p0,p1)\) 即所求。
现在只需要判断路径是否有交。
若 \(p0\neq p1\),则一定有交。
否则若 \(d_{p0}=\max(d_{lca(a,b)},d_{lca(c,d)})\),也有交。
否则路径不相交。

树上启发式合并

对于以 u 为根的子树

①. 先统计它轻子树(轻儿子为根的子树)的答案,统计完后删除信息

②. 再统计它重子树(重儿子为根的子树)的答案,统计完后保留信息

③. 然后再将重子树的信息合并到 u上

④. 再去遍历 u 的轻子树,然后把轻子树的信息合并到 u 上

⑤. 判断 u 的信息是否需要传递给它的父节点(u 是否是它父节点的重儿子)

void DFS(int root, int cur)
{
	cnt[node[cur].val]++;
	if (cnt[node[cur].val] > maxcnt)
	{
		ans[root] = node[cur].val;
		maxcnt = cnt[node[cur].val];
	}
	else if (cnt[node[cur].val] == maxcnt)
	{
		ans[root] += node[cur].val;
	}
	for (auto nxt : G[cur])
	{
		if (nxt == node[cur].pre)continue;
		if (nxt == node[root].son)continue;
		DFS(root, nxt);
	}
}
void DSU(int cur, bool keep)
{
	for (auto nxt : G[cur])
	{
		if (nxt == node[cur].pre)continue;
		if (nxt == node[cur].son)continue;
		DSU(nxt, false);
	}
	if (node[cur].son != -1)DSU(node[cur].son, true);
	if (node[cur].son != -1)
	{
		ans[cur] = ans[node[cur].son];
	}
	DFS(cur, cur);
	if (keep == false)
	{
		maxcnt = 0;
		for (int i = node[cur].dfn; i < node[cur].dfn + node[cur].siz; ++i)
		{
			cnt[node[node[i].idx].val]--;
		}
	}
}

数学

逆元

快速幂法

class INV
{
public:
	void init(int P)
	{
		this->P = P;
	}
	int operator[](int x)
	{
		return Pow(x % P, P - 2);
	}
private:
	int P = 0;
	/*====================*/
	int Pow(int a, int b)
	{
		int res = 1;
		while (b)
		{
			if (b & 1)
			{
				res = (res * a) % P;
			}
			b >>= 1, a = (a * a) % P;
		}
		return res;
	}
};

线性递推法

class INV
{
public:
	~INV(void)
	{
		delete[] inv;
	}
	int operator[](int x)
	{
		return inv[x];
	}
	void init(int n, int P)
	{
		inv = new int[n + 1];
		inv[0] = 0, inv[1] = 1;
		for (int i = 2; i <= n; ++i)
		{
			inv[i] = (P - P / i) * inv[P % i] % P;
		}
	}
private:
	int* inv = NULL;
};

扩展欧几里得法

class INV
{
public:
	void init(int P)
	{
		this->P = P;
	}
	int operator[](int x)
	{
		int a, b;
		exgcd(x, P, a, b);
		return (a % P + P) % P;
	}
private:
	int P = 0;
	/*====================*/
	void exgcd(int a, int b, int& x, int& y)
	{
		if (b == 0)
		{
			x = 1, y = 0;
		}
		else
		{
			exgcd(b, a % b, y, x);
			y -= a / b * x;
		}
	}
};

质数

欧拉筛法

class Prime
{
public:
	~Prime(void)
	{
		delete[] vis;
		delete[] table;
	}
	int size(void)
	{
		return cnt;
	}
	void init(int n)
	{
		Euler(n);
	}
	bool operator()(int x)
	{
		return vis[x];
	}
	int operator[](int x)
	{
		return table[x];
	}
private:
	int cnt = 0;
	bool* vis = NULL;
	int* table = NULL;
	/*====================*/
	void Euler(int n)
	{
		vis = new bool[n + 1];
		table = new int[n + 1];
		for (int i = 0; i <= n; ++i)
		{
			vis[i] = true;
		}
		vis[0] = vis[1] = false;
		for (int i = 2; i <= n; ++i)
		{
			if (vis[i])table[++cnt] = i;
			for (int j = 1; j <= cnt; ++j)
			{
				if (i * table[j] > n)break;
				vis[i * table[j]] = false;
				if (i % table[j] == 0)break;
			}
		}
	}
};

六倍试除法

class Prime
{
public:
	bool operator()(int x)
	{
		if (x <= 1)return false;
		if (x == 2 || x == 3 || x == 5)return true;
		if (x % 2 == 0 || x % 3 == 0)return false;
		for (int i = 5; i * i <= x; i += 6)
		{
			if (x % i == 0 || x % (i + 2) == 0)
			{
				return false;
			}
		}
		return true;
	}
};

Miller-Rabin

class Prime
{
public:
	bool operator()(lnt x)
	{
		if (x < 3 || x % 2 == 0) return x == 2;
		lnt a = x - 1, b = 0;
		while (a % 2 == 0) a /= 2, ++b;
		//lnt lib[] = { 2,7,61 };
		lnt lib[] = { 2,325,9375,28178,450775,9780504,1795265022 };
		for (lnt r : lib)
		{
			lnt v = Pow(r, a, x);
			if (v == 1 || v == x - 1 || v == 0) continue;
			for (lnt j = 1; j <= b; j++)
			{
				v = Mul(v, v, x);
				if (v == x - 1 && j != b) { v = 1; break; }
				if (v == 1) return false;
			}
			if (v != 1) return false;
		}
		return true;
	}
private:
	lnt Mul(lnt a, lnt b, lnt p)
	{
		lnt res = 0;
		while (b != 0)
		{
			if (b % 2 == 1)
			{
				res = (res + a) % p;
			}
			b /= 2, a = (a * 2) % p;
		}
		return res;
	}
	lnt Pow(lnt a, lnt b, lnt p)
	{
		lnt res = 1;
		while (b != 0)
		{
			if (b % 2 == 1)
			{
				res = Mul(res, a, p);
			}
			b /= 2, a = Mul(a, a, p);
		}
		return res;
	}
};

快速幂

int Pow(int a, int b, int p)
{
    int res = 1;
    while (b)
    {
        if (b & 1)
        {
            res = (res * a) % p;
        }
        b >>= 1, a = (a * a) % p;
    }
    return res;
}

龟速乘

int Mul(int a, int b, int p)
{
    int res = 0;
    while (b)
    {
        if (b & 1)
        {
            res = (res + a) % p;
        }
        b >>= 1, a = (a * 2) % p;
    }
    return res;
}
lnt Mul(lnt a, lnt b, lnt p)
{
	return (a * b - (lnt)(a / (long double)p * b + 1e-3) * p + p) % p;
}

逆序对

template<class Type>
class _CountInversions
{
public:
	lnt operator()(int n, Type arr[])
	{
		res = 0;
		a = new Type[n + 1];
		temp = new Type[n + 1];
		for (int i = 1; i <= n; ++i)
		{
			a[i] = arr[i];
		}
		MergeSort(1, n);
		delete[] a; delete[] temp;
		return res;
	}
private:
	Type* a = NULL;
	lnt res = 0;
	Type* temp = NULL;
	/*====================*/
	void MergeSort(int l, int r)
	{
		if (l < r)
		{
			int i = l;
			int mid = (l + r) >> 1;
			int p = l, q = mid + 1;
			MergeSort(l, mid + 0);
			MergeSort(mid + 1, r);
			while (p <= mid && q <= r)
			{
				if (a[p] <= a[q])
				{
					temp[i++] = a[p++];
				}
				else
				{
					temp[i++] = a[q++];
					res += (lnt)(mid - p + 1);
				}
			}
			while (p <= mid)temp[i++] = a[p++];
			while (q <= r)	temp[i++] = a[q++];
			for (i = l; i <= r; i++)a[i] = temp[i];
		}
	}
};

多项式

快速傅里叶变换

typedef complex<double> Comp;

const ll SIZE = 4000000 + 10;
const double PI = acos(-1.0);

Comp temp[SIZE];
void FFT(Comp* p, ll len, ll inv)//inv=+1 FFT;inv=-1 IFFT
{
	if (len == 1) return;
	const int E = 0, O = len / 2;
	for (ll i = 0; i < len; ++i) temp[i] = p[i];
	for (ll i = 0; i < len; ++i)
	{
		if ((i & 1) == 1)p[i / 2 + O] = temp[i];
		if ((i & 1) == 0)p[i / 2 + E] = temp[i];
	}
	Comp* pe = p + E; FFT(pe, len / 2, inv);
	Comp* po = p + O; FFT(po, len / 2, inv);
	Comp omega(1, 0);
	const double Angle = 2 * PI / len;
	const Comp step(cos(Angle), sin(inv * Angle));
	for (ll k = 0; k < len / 2; ++k, omega *= step)
	{
		temp[k + E] = pe[k] + omega * po[k];
		temp[k + O] = pe[k] - omega * po[k];
	}
	for (ll i = 0; i < len; ++i) p[i] = temp[i];
}

离散对数

ll BSGS(ll a, ll b, ll m)
{
    static unordered_map<ll, ll> hs;
    hs.clear();
    ll cur = 1, t = sqrt(m) + 1;
    for (int B = 1; B <= t; ++B)
    {
        (cur *= a) %= m;
        hs[b * cur % m] = B; // 哈希表中存B的值
    }
    ll now = cur; // 此时cur = a^t
    for (int A = 1; A <= t; ++A)
    {
        auto it = hs.find(now);
        if (it != hs.end())
            return A * t - it->second;
        (now *= cur) %= m;
    }
    return -1; // 没有找到,无解
}

欧拉函数

试除法

class PHI
{
public:
    int operator[](int x)
    {
        return GetPhi(x);
    }
private:
    int GetPhi(int x) 
    {
        int res = x;
        for (int i = 2; i * i <= x; ++i)
        {
            if (x % i == 0) 
            {
                res = res / i * (i - 1);
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) res = res / x * (x - 1);
        return res;
    }
};

欧拉筛法

class PHI
{
public:
	~PHI(void)
	{
		delete[] phi;
	}
	void init(int n)
	{
		GetPhi(n);
	}
	int operator[](int x)
	{
		return phi[x];
	}
private:
	int* phi = NULL;
	void GetPhi(int n)
	{
		phi = new int[n + 1];
		bool* vis = new bool[n + 1];
		int* table = new int[n + 1];
		for (int i = 0; i <= n; ++i)
		{
			vis[i] = true;
		}
		int cnt = 0; phi[1] = 1;
		for (int i = 2; i <= n; ++i)
		{
			if (vis[i])
			{
				phi[i] = i - 1;
				table[++cnt] = i;
			}
			for (int j = 1; j <= cnt; ++j)
			{
				if (i * table[j] > n)break;
				vis[i * table[j]] = false;
				if (i % table[j] == 0)
				{
					phi[i * table[j]] = phi[i] * table[j]; break;
				}
				else
				{
					phi[i * table[j]] = phi[i] * (table[j] - 1);
				}
			}
		}
		delete[] vis; delete[] table;
	}
};

欧拉降幂

class EX_Euler
{
public:
	int operator()(int a, string s, int p)
	{
		int b = 0;
		bool flag = false;
		int phi = GetPhi(p);
		for (auto c : s)
		{
			b = (b * 10 + c - '0');
			if (b >= phi)flag = true, b %= phi;
		}
		if (flag)b += phi; return Pow(a % p, b, p);
	}
private:
	int GetPhi(int x)
	{
		int res = x;
		for (int i = 2; i * i <= x; ++i)
		{
			if (x % i == 0)
			{
				res = res / i * (i - 1);
				while (x % i == 0) x /= i;
			}
		}
		if (x > 1) res = res / x * (x - 1);
		return res;
	}
	int Pow(int a, int b, int p)
	{
		int res = 1;
		while (b != 0)
		{
			if (b % 2 == 1)
			{
				res = (res * a) % p;
			}
			b /= 2, a = (a * a) % p;
		}
		return res;
	}
};

欧几里得

最大公因数

int gcd(int a, int b)
{
	return b == 0 ? a : gcd(b, a % b);
}

最小公倍数

int lcm(int a, int b)
{
	return a / gcd(a, b) * b;
}

扩展欧几里得

void exgcd(int a, int b, int& x, int& y)
{
	if (b == 0)
	{
		x = 1, y = 0;
	}
	else
	{
		exgcd(b, a % b, y, x);
		y -= a / b * x;
	}
}

分解质因数

欧拉筛优化

void PFF(int x, vector<int>& num, vector<int>& cnt)
{
	for (int i = 1; i <= prime.size(); ++i)
	{
		if (prime[i] * prime[i] > x)break;
		if (x % prime[i] == 0)
		{
			num.push_back(prime[i]);
			cnt.push_back(0);
			while (x % prime[i] == 0)
			{
				cnt.back()++;
				x /= prime[i];
			}
		}
	}
	if (x != 1)
	{
		num.push_back(x);
		cnt.push_back(1);
	}
}

Pollard_Rho

class Pollard_Rho
{
public:
	void operator()(lnt X, vector<lnt>& num, vector<lnt>& cnt)
	{
		GetAllFactor(X, num);
		unordered_map<lnt, lnt>cntp; for (auto p : num)cntp[p]++;
		sort(num.begin(), num.end()); num.erase(unique(num.begin(), num.end()), num.end());
		for (auto p : num)cnt.push_back(cntp[p]);
	}
private:
	lnt gcd(lnt a, lnt b)
	{
		return b == 0 ? a : gcd(b, a % b);
	}
	lnt Mul(lnt a, lnt b, lnt p)
	{
		return (__int128)a * b % p;
	}
	lnt Pow(lnt a, lnt b, lnt p)
	{
		lnt res = 1;
		while (b != 0)
		{
			if (b % 2 == 1)
			{
				res = Mul(res, a, p);
			}
			b /= 2, a = Mul(a, a, p);
		}
		return res;
	}
	bool Check(lnt x)
	{
		if (x < 3 || x % 2 == 0) return x == 2;
		lnt a = x - 1, b = 0;
		while (a % 2 == 0) a /= 2, ++b;
		//lnt lib[] = { 2,7,61 };
		lnt lib[] = { 2,325,9375,28178,450775,9780504,1795265022 };
		for (lnt r : lib)
		{
			lnt v = Pow(r, a, x);
			if (v == 1 || v == x - 1 || v == 0) continue;
			for (lnt j = 1; j <= b; j++)
			{
				v = Mul(v, v, x);
				if (v == x - 1 && j != b) { v = 1; break; }
				if (v == 1) return false;
			}
			if (v != 1) return false;
		}
		return true;
	}
	lnt GetFactor(lnt X)
	{
		if (X == 4)return 2;
		if (Check(X))return X;
		mt19937 rng(time(NULL));
		while (1)
		{
			lnt c = rng() % (X - 1) + 1;
			auto f = [=](lnt x) { return ((__int128)x * x + c) % X; };
			lnt t = 0, r = 0, p = 1, q;
			do
			{
				for (int i = 0; i < 128; ++i)
				{
					t = f(t), r = f(f(r));
					if (t == r || (q = (__int128)p * abs(t - r) % X) == 0)break;
					p = q;
				}
				lnt d = gcd(p, X); if (d > 1)return d;
			} while (t != r);
		}
	}
	void GetAllFactor(lnt X, vector<lnt>& lib)
	{
		lnt fac = GetFactor(X);
		if (fac == X)lib.push_back(fac);
		else GetAllFactor(fac, lib), GetAllFactor(X / fac, lib);
	}
}PFF;

获得全部因数

void GetDivisor(int x, vector<int>& divisor)
{
	vector<int>num, cnt; 
	PFF(x, num, cnt);
	divisor.push_back(1);
	for (int i = 0; i < num.size(); ++i)
	{
		int val = 1;
		int lim = divisor.size();
		for (int j = 1; j <= cnt[i]; ++j)
		{
			val *= num[i];
			for (int k = 0; k < lim; ++k)
			{
				divisor.push_back(divisor[k] * val);
			}
		}
	}
}

枚举

排列

全排列

void AllPermutation(int l, int r)
{
	vector<int>p;
	for (int i = l; i <= r; ++i)
	{
		p.push_back(i);
	}
	do
	{
		//do something
	} while (next_permutation(p.begin(), p.end()));
}

子集

枚举全部子集

void AllSubset(int s)
{
	for (int i = s; i; i = (i - 1) & s)
	{
		//do something
	}
}

枚举k大小子集

void GospersHack(int k, int n)
{
	int cur = (1 << k) - 1, limit = (1 << n);
	while (cur < limit)
	{
		// do something
		int lb = cur & -cur, r = cur + lb;
		cur = (((r ^ cur) >> 2) / lb) | r;
	}
}

随机化

模拟退火

#include<bits/stdc++.h>
using namespace std;
/*====================*/
#define endl "\n"
/*====================*/
typedef long long lnt;
/*====================*/
const int N = 1e3 + 10;
/*====================*/
double begintime = 0;
bool TLE(void)
{
	if ((clock() - begintime) / CLOCKS_PER_SEC > 0.9)
	{
		return true;
	}
	return false;
}
/*====================*/
int n;
/*====================*/
struct Node
{
	double w, x, y;
	Node(double _w = 0, double _x = 0, double _y = 0)
	{
		w = _w, x = _x, y = _y;
	}
};
Node node[N];
/*====================*/
double ansx, ansy, ansSigma = 1e18;
/*====================*/
double GetSigma(double x, double y)
{
	double res = 0;
	for (int i = 1; i <= n; ++i)
	{
		double dx = node[i].x - x;
		double dy = node[i].y - y;
		res += sqrt(dx * dx + dy * dy) * node[i].w * 100;
	}
	if (res < ansSigma)
	{
		ansx = x, ansy = y, ansSigma = res;
	}
	return res;
}
/*====================*/
double Rand() { return (double)rand() / RAND_MAX; }
/*====================*/
void SA(void)
{
	double curx = 0, cury = 0, curSigma = 0;
	for (int i = 1; i <= n; ++i)
	{
		curx += node[i].x, cury += node[i].y;
	}
	curx /= n, cury /= n; curSigma = GetSigma(curx, cury);

	double t = 1e4;
	while (t > 5e-4)
	{
		double nxtx = curx + t * (Rand() * 2.0 - 1.0);
		double nxty = cury + t * (Rand() * 2.0 - 1.0);
		double nxtSigma = GetSigma(nxtx, nxty);
		double delta = nxtSigma - curSigma;
		if (exp(-delta / t) > Rand())
		{
			curx = nxtx, curx = nxty, curSigma = nxtSigma;
		}
		t *= 0.9996;
	}
	for (int i = 1; i <= 5000; ++i) 
	{
		double nxtx = ansx + t * (Rand() * 2 - 1);
		double nxty = ansy + t * (Rand() * 2 - 1);
		double nxtSigma = GetSigma(nxtx, nxty);
	}
}
/*====================*/
void Solve(void)
{
	cin >> n;
	for (int i = 1; i <= n; ++i)
	{
		double w, x, y;
		cin >> x >> y >> w;
		node[i] = Node(w, x, y);
	}
	while (!TLE())SA();
	printf("%.3f %.3f\n", ansx, ansy);
}
/*====================*/
int main()
{
#ifndef ONLINE_JUDGE
	freopen("IN.txt", "r+", stdin);
#endif
	srand(time(0)); begintime = clock();
	ios::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	int T = 1; //cin >> T;
	while (T--)Solve();
	return 0;
}

字符串

Hash

class Hash
{
public:
	void Init(const string& str, lnt base)
	{
		powbase = new lnt[str.size()];
		invbase = new lnt[str.size()];
		sumhash = new lnt[str.size()];
		/*====================*/
		for (int i = 0; i < str.size(); ++i)
		{
			if (i == 0)powbase[i] = 1;
			else powbase[i] = powbase[i - 1] * base % MOD;
		}
		base = inv[base];
		for (int i = 0; i < str.size(); ++i)
		{
			if (i == 0)invbase[i] = 1;
			else invbase[i] = invbase[i - 1] * base % MOD;
		}
		for (int i = 0; i < str.size(); ++i)
		{
			if (i == 0)sumhash[i] = str[i] * powbase[i] % MOD;
			else sumhash[i] = (sumhash[i - 1] + str[i] * powbase[i]) % MOD;
		}
	}
	lnt operator()(int l, int r)
	{
		return (sumhash[r] - (l > 0 ? sumhash[l - 1] : 0) + MOD) * invbase[l] % MOD;
	}
private:
	lnt* powbase = NULL;
	lnt* invbase = NULL;
	lnt* sumhash = NULL;
};

Split

vector<string> Split(string str, char split)
{
	vector<string>res;
	istringstream iss(str); string token;
	while (getline(iss, token, split))
	{
		if (token != "")
		{
			res.push_back(token);
		}
	}
	return res;
}

Z函数

vector<int> Z_Function(const string& str)
{
	int n = str.size() - 1;
	vector<int>z(str.size());
	int l = 1, r = 1; z[1] = n;
	for (int i = 2; i <= n; ++i)
	{
		z[i] = (i <= r ? min(z[i - l + 1], r - i + 1) : 0);
		while (i + z[i] <= n && str[1 + z[i]] == str[i + z[i]])z[i]++;
		if (i + z[i] - 1 > r)r = i + z[i] - 1, l = i;
	}
	return z;
}

字典树

Trie

class Trie
{
public:
	void Init(int sigma_s, int size_s = 128)
	{
		cnt = 0; root = ++cnt;
		siz.assign(sigma_s + 2, 0);
		trie.assign(sigma_s + 2, vector<int>(size_s + 1));
	}
	void Insert(const string& str)
	{
		int cur = root; siz[cur]++;
		for (int i = 0; i < str.size(); ++i)
		{
			if (trie[cur][str[i]] == 0)
			{
				trie[cur][str[i]] = ++cnt;
			}
			siz[cur = trie[cur][str[i]]]++;
		}
	}
	int Query(const string& str)
	{
		int cur = root;
		for (int i = 0; i < str.size(); ++i)
		{
			if (trie[cur][str[i]] == 0)
			{
				return 0;
			}
			cur = trie[cur][str[i]];
		}
		return siz[cur];
	}
private:
	int root, cnt;
	vector<int>siz;
	vector<vector<int>>trie;
};

可持久化01Trie

int root[N], tot;
int siz[35 * N];
int trie[35 * N][2];
/*====================*/
void Insert(int pre, int cur, lnt num)
{
	for (int i = 32; i >= 0; --i)
	{
		siz[cur] = siz[pre] + 1;
		int bit = (num & (1ll << i)) ? 1 : 0;
		trie[cur][bit ^ 1] = trie[pre][bit ^ 1], trie[cur][bit] = ++tot;
		pre = trie[pre][bit]; cur = trie[cur][bit];
	}
	siz[cur] = siz[pre] + 1;
}
lnt Query(int cur, lnt num, int k)
{
	lnt ans = 0;
	for (int i = 32; i >= 0; --i)
	{
		int bit = (num & (1ll << i)) ? 1 : 0;
		if (siz[trie[cur][bit ^ 1]] >= k)
		{
			ans += 1ll << i;
			cur = trie[cur][bit ^ 1];
		}
		else
		{
			k -= siz[trie[cur][bit ^ 1]];
			cur = trie[cur][bit];
		}
	}
	return ans;
}

表达式

获取优先级

int GetPriority(char c)
{
	if (c == '*')return 0;
	if (c == '+')return -1;
	return -2;
}

中缀转后缀

string PostfixExpression(string str)
{
	string res;
	stack<char>stk;
	for (auto c : str)
	{
		if (c == '_')
		{
			res.push_back(c);
		}
		if (c == '(' || c == ')')
		{
			if (c == '(')
			{
				stk.push('(');
			}
			if (c == ')')
			{
				while (!stk.empty() && stk.top() != '(')
				{
					res.push_back(stk.top()); stk.pop();
				}
				stk.pop();
			}
		}
		if (c == '+' || c == '*')
		{
			while (!stk.empty() && GetPriority(stk.top()) >= GetPriority(c))
			{
				res.push_back(stk.top()); stk.pop();
			}
			stk.push(c);
		}
	}
	while (!stk.empty())
	{
		res.push_back(stk.top()); stk.pop();
	}
	return res;
}

建立表达式树

struct Node
{
	int val;
	char tag;
	Node* lch, * rch;
	Node(int _val = 0, char _tag = ' ', Node* _lch = NULL, Node* _rch = NULL)
	{
		val = _val, tag = _tag;
		lch = _lch, rch = _rch;
	}
};
Node* Build(string str)
{
	stack<Node*>stk;
	for (auto c : str)
	{
		if (c == '0' || c == '1')
		{
			stk.push(new Node(c - '0', ' ', NULL, NULL));
		}
		else
		{
			Node* rch = stk.top(); stk.pop();
			Node* lch = stk.top(); stk.pop();
			stk.push(new Node(((c == '&') ? (lch->val & rch->val) : (lch->val | rch->val)), c, lch, rch));
		}
	}
	return stk.top();
}

数据结构

莫队

int n, m;
/*====================*/
int S;
struct Query
{
	int l, r, idx;
	Query(int _l = 0, int _r = 0, int _idx = 0)
	{
		l = _l, r = _r, idx = _idx;
	}
	friend bool operator<(const Query& a, const Query& b)
	{
		return (a.l / S == b.l / S) ? (((a.l / S) & 1) ? (a.r > b.r) : (a.r < b.r)) : (a.l < b.l);
	}
}query[M];
/*====================*/
int ans[M];
/*====================*/
void Add(int pos)
{

}
void Del(int pos)
{

}
/*====================*/
void Solve(void)
{
	cin >> n >> m;
	S = n / sqrt(m) + 1;
	for (int i = 1; i <= m; ++i)
	{
		int l, r; cin >> l >> r;
		query[i] = Query(l, r, i);
	}
	sort(query + 1, query + 1 + m);
	int l = 1, r = 0;
	for (int i = 1; i <= m; ++i)
	{
		while (query[i].l < l)Add(--l);
		while (r < query[i].r)Add(++r);
		while (l < query[i].l)Del(l++);
		while (query[i].r < r)Del(r--);
		//获得ans[query[i].idx];
	}
}

猫树

#include<iostream>
using namespace std;

const int N = 1 << 20;
const int LEVEL = 20;

int a[N];
int lg[N];
int pos[N];
int MaoA[LEVEL][N];//最大子段和
int MaoB[LEVEL][N];//最大连续和

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

void Build(int p, int l, int r, int level)
{
	if (l == r) { pos[l] = p; return; }
	int mid = (l + r) >> 1;
	int tempA, tempB;
	//the left
	MaoA[level][mid] = MaoB[level][mid] = a[mid];
	tempA = max(a[mid], 0), tempB = a[mid];
	for (int i = mid - 1; i >= l; --i)
	{
		tempA += a[i]; MaoA[level][i] = max(MaoA[level][i + 1], tempA); tempA = max(tempA, 0);
		tempB += a[i]; MaoB[level][i] = max(MaoB[level][i + 1], tempB);
	}
	//the right
	MaoA[level][mid + 1] = MaoB[level][mid + 1] = a[mid + 1];
	tempA = max(a[mid + 1], 0), tempB = a[mid + 1];
	for (int i = mid + 2; i <= r; ++i)
	{
		tempA += a[i]; MaoA[level][i] = max(MaoA[level][i - 1], tempA); tempA = max(tempA, 0);
		tempB += a[i]; MaoB[level][i] = max(MaoB[level][i - 1], tempB);
	}
	//
	Build(ls(p), l, mid, level + 1); Build(rs(p), mid + 1, r, level + 1);
}
int Ask(int l, int r)
{
	if (l == r)return a[l];
	int level = (lg[pos[l]] - lg[pos[l] ^ pos[r]]);
	return max(max(MaoA[level][l], MaoA[level][r]), MaoB[level][l] + MaoB[level][r]);
}

int main()
{
	int n; cin >> n;
	int len = 1; while (len < n)len <<= 1;
	for (int i = 2; i < N; ++i)lg[i] = lg[i >> 1] + 1;
	for (int i = 1; i <= n; ++i)cin >> a[i];
	Build(1, 1, len, 1);
	int m; cin >> m;
	for (int i = 1; i <= m; ++i)
	{
		int l, r; cin >> l >> r;
		cout << Ask(l, r) << endl;
	}
	return 0;
}

ST表

template<class Type>
class _ST
{
public:
	~_ST(void)
	{
		delete[] log2;
		for (int i = 0; i < logn; ++i)
		{
			delete[] table[i];
		}
		delete[] table;
	}
	Type operator()(int l, int r)
	{
		int d = log2[r - l + 1];
		if (flag)
		{
			return max(table[d][l], table[d][r - (1 << d) + 1]);
		}
		else
		{
			return min(table[d][l], table[d][r - (1 << d) + 1]);
		}
	}
	void init(int n, Type arr[], bool flag)
	{
		this->n = n;
		this->flag = flag;
		while ((1 << logn) <= n)
		{
			logn++;
		}
		table = new Type * [logn];
		for (int i = 0; i < logn; ++i)
		{
			table[i] = new Type[n+1];
		}
		log2 = new int[n + 1]; log2[0] = -1;
		for (int i = 1; i <= n; ++i)
		{
			log2[i] = log2[i >> 1] + 1;
		}
		for (int i = 1; i <= n; ++i)
		{
			table[0][i] = arr[i];
		}
		for (int j = 1; (1 << j) <= n; ++j)
		{
			for (int i = 1; i + (1 << j) - 1 <= n; ++i)
			{
				if (flag)
				{
					table[j][i] = max(table[j - 1][i], table[j - 1][i + (1 << (j - 1))]);
				}
				else
				{
					table[j][i] = min(table[j - 1][i], table[j - 1][i + (1 << (j - 1))]);
				}
			}
		}
	}
private:
	int n = 0;
	int logn = 1;
	int* log2 = NULL;
	Type** table = NULL;
	/*====================*/
#define MAX true
#define MIN false
	bool flag = MIN;
};

扫描线

矩形面积并

namespace ScanLine
{
	const int N = 1e5 + 10;
	/*====================*/
	struct Rectangle
	{
		double x1, y1;
		double x2, y2;
	};
	Rectangle rectangle[N];
	/*====================*/
	vector<double>pos;
	/*====================*/
	struct Line
	{
		int val;
		int l, r; 
		double h;
		Line(int _l = 0, int _r = 0, double _h = 0, int _val = 0)
		{
			l = _l, r = _r, h = _h, val = _val;
		}
		friend bool operator<(const Line& a, const Line& b)
		{
			if (a.h != b.h)
			{
				return a.h < b.h;
			}
			else
			{
				return  a.val > b.val;
			}
		}
	};
	vector<Line>line;
	/*====================*/
	struct Tree
	{
		int l, r;
		int cnt; double len;
	};
	Tree tree[N << 3];
	int ls(int p)
	{
		return p << 1;
	}
	int rs(int p)
	{
		return p << 1 | 1;
	}
	void PushUp(int p)
	{
		if (tree[p].cnt >= 1)
		{
			tree[p].len = pos[tree[p].r] - pos[tree[p].l - 1];
		}
		else
		{
			if (tree[p].l != tree[p].r)
			{
				tree[p].len = tree[ls(p)].len + tree[rs(p)].len;
			}
			else
			{
				tree[p].len = 0;
			}
		}
	}
	void Build(int p, int l, int r)
	{
		tree[p].l = l, tree[p].r = r;
		tree[p].cnt = 0; tree[p].len = 0;
		if (tree[p].l != tree[p].r)
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			Build(ls(p), l, mid + 0);
			Build(rs(p), mid + 1, r);
		}
	}
	void Change(int p, int l, int r, int d)
	{
		if (l <= tree[p].l && tree[p].r <= r)
		{
			tree[p].cnt += d; PushUp(p);
		}
		else
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			if (l <= mid)Change(ls(p), l, r, d);
			if (mid < r) Change(rs(p), l, r, d);
			PushUp(p);
		}
	}
	/*====================*/
	double Init(void)
	{
		int n; cin >> n;
		pos.clear(); line.clear();
		for (int i = 1; i <= n; ++i)
		{
			double x1, y1; cin >> x1 >> y1;//左上
			double x2, y2; cin >> x2 >> y2;//右下
			pos.push_back(x1); pos.push_back(x2);
			rectangle[i].x1 = x1; rectangle[i].y1 = y1;
			rectangle[i].x2 = x2; rectangle[i].y2 = y2;
		}
		sort(pos.begin(), pos.end());
		pos.erase(unique(pos.begin(), pos.end()), pos.end());
		for (int i = 1; i <= n; ++i)
		{
			int l = lower_bound(pos.begin(), pos.end(), rectangle[i].x1) - pos.begin();
			int r = lower_bound(pos.begin(), pos.end(), rectangle[i].x2) - pos.begin();
			line.push_back(Line(l, r, rectangle[i].y1, +1));
			line.push_back(Line(l, r, rectangle[i].y2, -1));
		}
		sort(line.begin(), line.end());
		Build(1, 1, pos.size() - 1);
		bool flag = true;
		double ans = 0.0;
		double last = 0.0;
		auto it = line.begin();
		while (it != line.end())
		{
			double high = it->h;
			if (flag)last = high, flag = false;
			ans += (high - last) * tree[1].len;
			while (it != line.end() && it->h == high)
			{
				Change(1, it->l + 1, it->r, it->val); it++;
			}
			last = high;
		}
		return ans;
	}
}

矩形面积交

namespace ScanLine
{
	const int N = 1e5 + 10;
	/*====================*/
	struct Rectangle
	{
		double x1, y1;
		double x2, y2;
	};
	Rectangle rectangle[N];
	/*====================*/
	vector<double>pos;
	/*====================*/
	struct Line
	{
		int val;
		int l, r; 
		double h;
		Line(int _l = 0, int _r = 0, double _h = 0, int _val = 0)
		{
			l = _l, r = _r, h = _h, val = _val;
		}
		friend bool operator<(const Line& a, const Line& b)
		{
			if (a.h != b.h)
			{
				return a.h < b.h;
			}
			else
			{
				return  a.val > b.val;
			}
		}
	};
	vector<Line>line;
	/*====================*/
	struct Tree
	{
		int cnt;
		int l, r;
		double len1;
		double len2;
	};
	Tree tree[N << 3];
	int ls(int p)
	{
		return p << 1;
	}
	int rs(int p)
	{
		return p << 1 | 1;
	}
	void PushUp(int p)
	{
		if (tree[p].cnt >= 1)
		{
			tree[p].len1 = pos[tree[p].r] - pos[tree[p].l - 1];
		}
		else
		{
			if (tree[p].l != tree[p].r)
			{
				tree[p].len1 = tree[ls(p)].len1 + tree[rs(p)].len1;
			}
			else
			{
				tree[p].len1 = 0;
			}
		}
		if (tree[p].cnt >= 2)
		{
			tree[p].len2 = pos[tree[p].r] - pos[tree[p].l - 1];
		}
		else
		{
			if (tree[p].l != tree[p].r)
			{
				if (tree[p].cnt == 1)
				{
					tree[p].len2 = tree[ls(p)].len1 + tree[rs(p)].len1;
				}
				else
				{
					tree[p].len2 = tree[ls(p)].len2 + tree[rs(p)].len2;
				}
			}
			else
			{
				tree[p].len2 = 0;
			}
		}
	}
	void Build(int p, int l, int r)
	{
		tree[p].cnt = 0;
		tree[p].l = l, tree[p].r = r;
		tree[p].len1 = 0; tree[p].len2 = 0;
		if (tree[p].l != tree[p].r)
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			Build(ls(p), l, mid + 0);
			Build(rs(p), mid + 1, r);
		}
	}
	void Change(int p, int l, int r, int d)
	{
		if (l <= tree[p].l && tree[p].r <= r)
		{
			tree[p].cnt += d; PushUp(p);
		}
		else
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			if (l <= mid)Change(ls(p), l, r, d);
			if (mid < r) Change(rs(p), l, r, d);
			PushUp(p);
		}
	}
	/*====================*/
	double Init(void)
	{
		int n; cin >> n;
		pos.clear(); line.clear();
		for (int i = 1; i <= n; ++i)
		{
			double x1, y1; cin >> x1 >> y1;//左上
			double x2, y2; cin >> x2 >> y2;//右下
			pos.push_back(x1); pos.push_back(x2);
			rectangle[i].x1 = x1; rectangle[i].y1 = y1;
			rectangle[i].x2 = x2; rectangle[i].y2 = y2;
		}
		sort(pos.begin(), pos.end());
		pos.erase(unique(pos.begin(), pos.end()), pos.end());
		for (int i = 1; i <= n; ++i)
		{
			int l = lower_bound(pos.begin(), pos.end(), rectangle[i].x1) - pos.begin();
			int r = lower_bound(pos.begin(), pos.end(), rectangle[i].x2) - pos.begin();
			line.push_back(Line(l, r, rectangle[i].y1, +1));
			line.push_back(Line(l, r, rectangle[i].y2, -1));
		}
		sort(line.begin(), line.end());
		Build(1, 1, pos.size() - 1);
		bool flag = true;
		double ans = 0.0;
		double last = 0.0;
		auto it = line.begin();
		while (it != line.end())
		{
			double high = it->h;
			if (flag)last = high, flag = false;
			ans += (high - last) * tree[1].len2;
			while (it != line.end() && it->h == high)
			{
				Change(1, it->l + 1, it->r, it->val); it++;
			}
			last = high;
		}
		return ans;
	}
}

矩形周长并

namespace ScanLine
{
	const int N = 1e5 + 10;
	/*====================*/
	struct Rectangle
	{
		double x1, y1;
		double x2, y2;
	};
	Rectangle rectangle[N];
	/*====================*/
	vector<double>pos;
	/*====================*/
	struct Line
	{
		int val;
		int l, r;
		double h;
		Line(int _l = 0, int _r = 0, double _h = 0, int _val = 0)
		{
			l = _l, r = _r, h = _h, val = _val;
		}
		friend bool operator<(const Line& a, const Line& b)
		{
			if (a.h != b.h)
			{
				return a.h < b.h;
			}
			else
			{
				return  a.val > b.val;
			}
		}
	};
	vector<Line>line;
	typedef vector<Line>::iterator iter;
	/*====================*/
	struct Tree
	{
		int l, r;
		int cnt; double len;
	};
	Tree tree[N << 3];
	int ls(int p)
	{
		return p << 1;
	}
	int rs(int p)
	{
		return p << 1 | 1;
	}
	void PushUp(int p)
	{
		if (tree[p].cnt >= 1)
		{
			tree[p].len = pos[tree[p].r] - pos[tree[p].l - 1];
		}
		else
		{
			if (tree[p].l != tree[p].r)
			{
				tree[p].len = tree[ls(p)].len + tree[rs(p)].len;
			}
			else
			{
				tree[p].len = 0;
			}
		}
	}
	void Build(int p, int l, int r)
	{
		tree[p].l = l, tree[p].r = r;
		tree[p].cnt = 0; tree[p].len = 0;
		if (tree[p].l != tree[p].r)
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			Build(ls(p), l, mid + 0);
			Build(rs(p), mid + 1, r);
		}
	}
	void Change(int p, int l, int r, int d)
	{
		if (l <= tree[p].l && tree[p].r <= r)
		{
			tree[p].cnt += d; PushUp(p);
		}
		else
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			if (l <= mid)Change(ls(p), l, r, d);
			if (mid < r) Change(rs(p), l, r, d);
			PushUp(p);
		}
	}
	/*====================*/
	double Init(void)
	{
		int n; cin >> n; double ans = 0;
		for (int i = 1; i <= n; ++i)
		{
			double x1, y1; cin >> x1 >> y1;//左上
			double x2, y2; cin >> x2 >> y2;//右下
			rectangle[i].x1 = x1; rectangle[i].y1 = y1;
			rectangle[i].x2 = x2; rectangle[i].y2 = y2;
		}
		/*====================*/
		pos.clear(); line.clear();
		for (int i = 1; i <= n; ++i)
		{
			pos.push_back(rectangle[i].x1);
			pos.push_back(rectangle[i].x2);
		}
		sort(pos.begin(), pos.end());
		pos.erase(unique(pos.begin(), pos.end()), pos.end());
		for (int i = 1; i <= n; ++i)
		{
			int l = lower_bound(pos.begin(), pos.end(), rectangle[i].x1) - pos.begin();
			int r = lower_bound(pos.begin(), pos.end(), rectangle[i].x2) - pos.begin();
			line.push_back(Line(l, r, rectangle[i].y1, +1));
			line.push_back(Line(l, r, rectangle[i].y2, -1));
		}
		sort(line.begin(), line.end());
		Build(1, 1, pos.size() - 1);
		double last1 = 0;
		for (iter it = line.begin(); it != line.end(); ++it)
		{
			Change(1, it->l + 1, it->r, it->val);
			ans += abs(tree[1].len - last1); last1 = tree[1].len;
		}
		/*====================*/
		pos.clear(); line.clear();
		for (int i = 1; i <= n; ++i)
		{
			pos.push_back(rectangle[i].y1);
			pos.push_back(rectangle[i].y2);
		}
		sort(pos.begin(), pos.end());
		pos.erase(unique(pos.begin(), pos.end()), pos.end());
		for (int i = 1; i <= n; ++i)
		{
			int l = lower_bound(pos.begin(), pos.end(), rectangle[i].y1) - pos.begin();
			int r = lower_bound(pos.begin(), pos.end(), rectangle[i].y2) - pos.begin();
			line.push_back(Line(l, r, rectangle[i].x1, +1));
			line.push_back(Line(l, r, rectangle[i].x2, -1));
		}
		sort(line.begin(), line.end());
		Build(1, 1, pos.size() - 1);
		double last2 = 0;
		for (iter it = line.begin(); it != line.end(); ++it)
		{
			Change(1, it->l + 1, it->r, it->val);
			ans += abs(tree[1].len - last2); last2 = tree[1].len;
		}
		/*====================*/
		return ans;
	}
}

可删堆

template<class Type, class Comp = greater<Type>>
class Heap
{
private:
	priority_queue<Type, vector<Type>, Comp>heap1;
	priority_queue<Type, vector<Type>, Comp>heap2;
public:
	Type top(void)
	{
		while (!heap2.empty() && heap1.top() == heap2.top())
		{
			heap1.pop(); heap2.pop();
		}
		return heap1.top();
	}
	void pop(void)
	{
		while (!heap2.empty() && heap1.top() == heap2.top())
		{
			heap1.pop(); heap2.pop();
		}
		heap1.pop();
	}
	int size(void)
	{
		return heap1.size() - heap2.size();
	}
	void clear(void)
	{
		while (!heap1.empty())heap1.pop();
		while (!heap2.empty())heap2.pop();
	}
	bool empty(void)
	{
		return heap1.size() == heap2.size();
	}
	void erase(Type val)
	{
		heap2.push(val);
	}
	void insert(Type val)
	{
		heap1.push(val);
	}
};

并查集

class DSU
{
public:
	~DSU(void)
	{
		delete[] pre; delete[] siz;
	}
	void init(int n)
	{
		if (pre != NULL)delete[] pre; pre = new int[n + 1];
		if (siz != NULL)delete[] siz; siz = new int[n + 1];
		for (int i = 0; i <= n; ++i)pre[i] = i, siz[i] = 1;
	}
	int operator[](int cur)
	{
		return find(cur);
	}
	void operator()(int u, int v)
	{
		u = find(u), v = find(v);
		if (siz[u] < siz[v])
		{
			pre[u] = v, siz[v] += siz[u];
		}
		else
		{
			pre[v] = u, siz[u] += siz[v];
		}
	}
private:
	int* pre = NULL, * siz = NULL;
	/*====================*/
	int find(int cur)
	{
		return cur == pre[cur] ? cur : pre[cur] = find(pre[cur]);
	}
};

主席树

template<class Type>
class ChairmanTree
{
public:
	~ChairmanTree(void)
	{
		delete[] root;
		delete[] node;
	}
	Type ask(int l, int r, int k)
	{
		return val_key[Ask(root[l - 1], root[r], 1, len, k)];
	}
	void init(int n, Type arr[])
	{
		vector<Type>line;
		for (int i = 1; i <= n; ++i)
		{
			line.push_back(arr[i]);
		}
		sort(line.begin(), line.end());
		line.erase(unique(line.begin(), line.end()), line.end());
		len = line.size();
		for (int i = 0; i < line.size(); ++i)
		{
			key_val[line[i]] = i + 1;
			val_key[i + 1] = line[i];
		}
		this->n = n;
		root = new int[n + 10];
		node = new Node[(n + 10) << 5];
		root[0] = Zero(1, len);
		for (int i = 1; i <= n; ++i)
		{
			root[i] = UpData(key_val[arr[i]], 1, len, root[i - 1]);
		}
	}
private:
	struct Node
	{
		int val = 0;
		int ls = 0, rs = 0;
	};
	/*====================*/
	int pos = 0;
	int* root = NULL;
	Node* node = NULL;
	int n = 0, len = 0;
	map<Type, int>key_val;
	map<int, Type>val_key;
	/*====================*/
	int Zero(int l, int r)
	{
		int root = ++pos;
		if (l == r)return root;
		int mid = (l + r) >> 1;
		node[root].ls = Zero(l, mid + 0);
		node[root].rs = Zero(mid + 1, r);
		return root;
	}
	int UpData(int k, int l, int r, int oldroot)
	{
		int newroot = ++pos; node[newroot] = node[oldroot]; node[newroot].val += 1;
		if (l == r)return newroot; int mid = (l + r) >> 1;
		if (k <= mid)node[newroot].ls = UpData(k, l, mid + 0, node[oldroot].ls);
		if (mid < k) node[newroot].rs = UpData(k, mid + 1, r, node[oldroot].rs);
		return newroot;
	}
	int Ask(int u, int v, int l, int r, int k)
	{
		if (l == r)return l; int mid = (l + r) >> 1;
		int x = node[node[v].ls].val - node[node[u].ls].val;
		if (k <= x)return Ask(node[u].ls, node[v].ls, l, mid, k);
		else return Ask(node[u].rs, node[v].rs, mid + 1, r, k - x);
	}
};

平衡树

Treap·权值树

template<class Type>
class Treap
{
public:
	~Treap(void)
	{
		Clear(root);
		delete null;
	}
	int size(void)
	{
		return count;
	}
	void clear(void)
	{
		count = 0;
		Clear(root);
		root = null;
	}
	bool empty(void)
	{
		return count == 0;
	}
	void erase(Type val)
	{
		count--; Delete(root, val);
	}
	void insert(Type val)
	{
		count++; Insert(root, val);
	}
	int operator()(Type valu)
	{
		return GetRankByValu(valu);
	}
	Type operator[](int rank)
	{
		return GetValuByRank(rank);
	}
private:
	struct Node
	{
		int siz = 0;
		Type val = Type();
		int priority = rand();
		Node* lch = NULL, * rch = NULL;
	};
	/*====================*/
	int count = 0;
	Node* null = new Node;
	Node* root = null;
	/*====================*/
	Node* Creat(Type val)
	{
		Node* node = new Node;
		node->lch = null;
		node->rch = null;
		node->val = val;
		node->siz = 1;
		return node;
	}

	void PushUp(Node* cur)
	{
		cur->siz = cur->lch->siz + cur->rch->siz + 1;
	}

	void LRotate(Node*& cur)
	{
		Node* son = cur->rch;
		cur->rch = son->lch; son->lch = cur; cur = son;
		PushUp(cur->lch); PushUp(cur);
	}
	void RRotate(Node*& cur)
	{
		Node* son = cur->lch;
		cur->lch = son->rch; son->rch = cur; cur = son;
		PushUp(cur->rch); PushUp(cur);
	}

	void Insert(Node*& cur, Type val)
	{
		if (cur == null)
		{
			cur = Creat(val);
		}
		else
		{
			if (val < cur->val)
			{
				Insert(cur->lch, val);
				if (cur->priority < cur->lch->priority)
				{
					RRotate(cur);
				}
			}
			else
			{
				Insert(cur->rch, val);
				if (cur->priority < cur->rch->priority)
				{
					LRotate(cur);
				}
			}
			PushUp(cur);
		}
	}

	void Delete(Node*& cur, Type val)
	{
		if (cur == null)return;
		if (val == cur->val)
		{
			if (cur->lch != null && cur->rch != null)
			{
				if (cur->lch->priority < cur->rch->priority)
				{
					LRotate(cur); Delete(cur->lch, val); PushUp(cur);
				}
				else
				{
					RRotate(cur); Delete(cur->rch, val); PushUp(cur);
				}
			}
			else if (cur->lch != null)
			{
				RRotate(cur); Delete(cur->rch, val); PushUp(cur);
			}
			else if (cur->rch != null)
			{
				LRotate(cur); Delete(cur->lch, val); PushUp(cur);
			}
			else
			{
				Node* temp = cur; cur = null; delete temp;
			}
		}
		else
		{
			if (val < cur->val)
			{
				Delete(cur->lch, val);
			}
			else
			{
				Delete(cur->rch, val);
			}
			PushUp(cur);
		}
	}

	Type GetValuByRank(int rank)
	{
		Node* cur = root;
		while (cur != null)
		{
			if (cur->lch->siz + 1 == rank)
			{
				return cur->val;
			}
			else
			{
				if (cur->lch->siz < rank)
				{
					rank -= cur->lch->siz + 1;
					cur = cur->rch;
				}
				else
				{
					cur = cur->lch;
				}
			}
		}
		return Type();
	}
	int GetRankByValu(Type valu)
	{
		int res = 1;
		Node* cur = root;
		while (cur != null)
		{
			if (cur->val < valu)
			{
				res += cur->lch->siz + 1;
				cur = cur->rch;
			}
			else
			{
				cur = cur->lch;
			}
		}
		return res;
	}

	void Clear(Node* cur)
	{
		if (cur != null)
		{
			Clear(cur->lch);
			Clear(cur->rch);
			delete cur;
		}
	}
};

Treap·序列树

namespace Treap
{
	struct Node
	{
		int siz = 0;
		int val = 0;
		int priority = rand();
		Node* lch = NULL, * rch = NULL;
	};
	/*====================*/
	Node* null = new Node;
	Node* root = null;
	/*====================*/
	Node* Creat(int val)
	{
		Node* node = new Node;
		node->lch = null;
		node->rch = null;
		node->val = val;
		node->siz = 1;
		return node;
	}
	/*====================*/
	void PushUp(Node* cur)
	{
		cur->siz = cur->lch->siz + cur->rch->siz + 1;
	}
	void PushDown(Node* cur)
	{
		/*预留*/
	}
	/*====================*/
	Node* Build(int l, int r)
	{
		if (l > r)return null;
		int mid = (l + r) >> 1;
		Node* cur = Creat(arr[mid]);
		cur->lch = Build(l, mid - 1);
		cur->rch = Build(mid + 1, r);
		/*=*/PushUp(cur); return cur;
	}
	/*====================*/
	Node* Merge(Node* ltree, Node* rtree)
	{
		if (ltree == null)return rtree;
		if (rtree == null)return ltree;
		PushDown(ltree); PushDown(rtree);
		if (ltree->priority < rtree->priority)
		{
			rtree->lch = Merge(ltree, rtree->lch);
			/*======*/PushUp(rtree); return rtree;
		}
		else
		{
			ltree->rch = Merge(ltree->rch, rtree);
			/*======*/PushUp(ltree); return ltree;
		}
	}
	/*====================*/
	void Lower_Split(Node* cur, int index, Node*& ltree, Node*& rtree)//index留在rtree
	{
		if (cur == null)
		{
			ltree = rtree = null; return;
		}
		PushDown(cur);
		if (cur->lch->siz + 1 < index)
		{
			Lower_Split(cur->rch, index - cur->lch->siz - 1, ltree, rtree);
			/*================*/cur->rch = ltree; PushUp(cur); ltree = cur;
		}
		else
		{
			Lower_Split(cur->lch, index, ltree, rtree);
			cur->lch = rtree; PushUp(cur); rtree = cur;
		}
	}
	void Upper_Split(Node* cur, int index, Node*& ltree, Node*& rtree)//index留在ltree
	{
		if (cur == null)
		{
			ltree = rtree = null; return;
		}
		PushDown(cur);
		if (cur->lch->siz < index)
		{
			Upper_Split(cur->rch, index - cur->lch->siz - 1, ltree, rtree);
			/*================*/cur->rch = ltree; PushUp(cur); ltree = cur;
		}
		else
		{
			Upper_Split(cur->lch, index, ltree, rtree);
			cur->lch = rtree; PushUp(cur); rtree = cur;
		}
	}
	/*====================*/
	void Clear(Node* cur)
	{
		if (cur != null)
		{
			Clear(cur->lch);
			Clear(cur->rch);
			delete cur;
		}
	}
	/*====================*/
	void Init(void)
	{
		root = Build(1, n); 
		/*操作*/
		Clear(root); root = null;
	}
}

Splay·权值树

template<class Type>
class Splay
{
public:
	~Splay(void)
	{
		Clear(root);
		delete null;
	}
	int size(void)
	{
		return count;
	}
	void clear(void)
	{
		Clear(root);
		root = null;
	}
	bool empty(void)
	{
		return count == 0;
	}
	Type pre(Type val)
	{
		root = splay(FindPre(root, val));
		return root->val;
	}
	Type nxt(Type val)
	{
		root = splay(FindNxt(root, val));
		return root->val;
	}
	void erase(Type val)
	{
		count--; root = Delete(FindByValu(root, val));
	}
	void insert(Type val)
	{
		count++; root = splay(Insert(root, val));
	}
	int operator()(Type val)
	{
		root = splay(FindByValu(root, val));
		return root->lch->siz + 1;
	}
	Type operator[](int rank)
	{
		root = splay(FindByRank(root, rank));
		return root->val;
	}
	Type lower_bound(Type val)
	{
		root = splay(FindLower(root, val));
		return root->val;
	}
	Type upper_bound(Type val)
	{
		root = splay(FindUpper(root, val));
		return root->val;
	}
private:
	struct Node
	{
		int siz = 0;
		Type val = Type();
		Node* fa = NULL;
		Node* lch = NULL;
		Node* rch = NULL;
	};
	/*====================*/
	typedef bool CHILD;
	const CHILD LCH = true;
	const CHILD RCH = false;
	/*====================*/
	int count = 0;
	Node* null = new Node;
	Node* root = null;
	/*====================*/
	CHILD Child(Node* cur)
	{
		Node* pre = cur->fa;
		if (pre->lch == cur)
		{
			return LCH;
		}
		else
		{
			return RCH;
		}
	}

	void PushUp(Node* cur)
	{
		cur->siz = cur->lch->siz + cur->rch->siz + 1;
	}

	void Del(Node* cur, Node* pre, CHILD WCH)
	{
		cur->fa = null;
		if (WCH == LCH)pre->lch = null;
		if (WCH == RCH)pre->rch = null;
	}
	void Add(Node* cur, Node* pre, CHILD WCH)
	{
		cur->fa = pre;
		if (WCH == LCH)pre->lch = cur;
		if (WCH == RCH)pre->rch = cur;
	}

	void LRotate(Node* cur)
	{
		Node* pre = cur->fa, * nxt = cur->lch, * anc = pre->fa;
		CHILD WCH = Child(pre);
		Del(nxt, cur, LCH); Del(cur, pre, RCH); Del(pre, anc, WCH);
		Add(nxt, pre, RCH); Add(pre, cur, LCH); Add(cur, anc, WCH);
		PushUp(pre); PushUp(cur);
	}
	void RRotate(Node* cur)
	{
		Node* pre = cur->fa, * nxt = cur->rch, * anc = pre->fa;
		CHILD WCH = Child(pre);
		Del(nxt, cur, RCH); Del(cur, pre, LCH); Del(pre, anc, WCH);
		Add(nxt, pre, LCH); Add(pre, cur, RCH); Add(cur, anc, WCH);
		PushUp(pre); PushUp(cur);
	}

	void Rotate(Node* cur)
	{
		if (Child(cur) == LCH)
		{
			RRotate(cur);
		}
		else
		{
			LRotate(cur);
		}
	}

	void Clear(Node* cur)
	{
		if (cur != null)
		{
			Clear(cur->lch);
			Clear(cur->rch);
			delete cur;
		}
	}

	Node* Creat(Type val)
	{
		Node* cur = new Node;
		cur->lch = null;
		cur->rch = null;
		cur->fa = null;
		cur->val = val;
		cur->siz = 1;
		return cur;
	}

	Node* splay(Node* cur)
	{
		while (true)
		{
			Node* pre = cur->fa;
			if (cur->fa == null)break;
			if (pre->fa == null)break;
			CHILD CHpre = Child(pre);
			CHILD CHcur = Child(cur);
			if (CHpre == CHcur)
			{
				Rotate(pre); Rotate(cur); continue;
			}
			if (CHpre != CHcur)
			{
				Rotate(cur); Rotate(cur); continue;
			}
		}
		if (cur->fa != null)Rotate(cur); return cur;
	}

	Node* Insert(Node* cur, Type val)
	{
		CHILD WCH = LCH; Node* pre = null;
		while (cur != null)
		{
			if (val < cur->val)
			{
				pre = cur; cur = cur->lch; WCH = LCH;
			}
			else
			{
				pre = cur; cur = cur->rch; WCH = RCH;
			}
		}
		cur = Creat(val); Add(cur, pre, WCH); return cur;
	}

	Node* Delete(Node* cur)
	{
		splay(cur);
		Node* lch = cur->lch;
		Node* rch = cur->rch;
		delete cur; return Merge(lch, rch);
	}

	Node* Merge(Node* ltree, Node* rtree)
	{
		if (ltree == null)
		{
			rtree->fa = null; return rtree;
		}
		if (rtree == null)
		{
			ltree->fa = null; return ltree;
		}
		ltree->fa = null; rtree->fa = null;
		if (ltree->siz < rtree->siz)
		{
			Node* cur = FindMax(ltree); splay(cur);
			Add(rtree, cur, RCH); PushUp(cur); return cur;
		}
		else
		{
			Node* cur = FindMin(rtree); splay(cur);
			Add(ltree, cur, LCH); PushUp(cur); return cur;
		}
	}

	Node* FindByValu(Node* cur, Type val)
	{
		Node* res = null;
		while (cur != null)
		{
			if (val == cur->val)
			{
				res = cur, cur = cur->lch;
			}
			else
			{
				if (val < cur->val)
				{
					cur = cur->lch;
				}
				else
				{
					cur = cur->rch;
				}
			}
		}
		return res;
	}
	Node* FindByRank(Node* cur, int rank)
	{
		while (cur != null)
		{
			if (cur->lch->siz + 1 == rank)
			{
				return cur;
			}
			else
			{
				if (cur->lch->siz < rank)
				{
					rank -= cur->lch->siz + 1;
					cur = cur->rch;
				}
				else
				{
					cur = cur->lch;
				}
			}
		}
		return null;
	}

	Node* FindLower(Node* cur, Type val)
	{
		Node* res = null;
		while (cur != null)
		{
			if (cur->val < val)
			{
				cur = cur->rch;
			}
			else
			{
				res = cur;
				cur = cur->lch;
			}
		}
		return res;
	}
	Node* FindUpper(Node* cur, Type val)
	{
		Node* res = null;
		while (cur != null)
		{
			if (val < cur->val)
			{
				res = cur;
				cur = cur->lch;
			}
			else
			{
				cur = cur->rch;
			}
		}
		return res;
	}

	Node* FindMin(Node* cur)
	{
		while (cur->lch != null)
		{
			cur = cur->lch;
		}
		return cur;
	}
	Node* FindMax(Node* cur)
	{
		while (cur->rch != null)
		{
			cur = cur->rch;
		}
		return cur;
	}

	Node* FindPre(Node* cur, Type val)
	{
		Node* res = null;
		while (cur != null)
		{
			if (cur->val < val)
			{
				res = cur;
				cur = cur->rch;
			}
			else
			{
				cur = cur->lch;
			}
		}
		return res;
	}
	Node* FindNxt(Node* cur, Type val)
	{
		Node* res = null;
		while (cur != null)
		{
			if (val < cur->val)
			{
				res = cur;
				cur = cur->lch;
			}
			else
			{
				cur = cur->rch;
			}
		}
		return res;
	}
};

珂朵莉树

template<class Type>
class Chtholly
{
public:
	void init(int n, Type arr[])
	{
		for (int i = 1; i <= n; ++i)
		{
			tree.insert(Node(i, i, arr[i]));
		}
	}
	void cover(int l, int r, Type val)
	{
		auto end = Split(r + 1), begin = Split(l);
		for (auto it = begin; it != end; ++it)
		{
			/*
				统计信息
			*/
		}
		tree.erase(begin, end);
		tree.insert(Node(l, r, val));
	}
private:
	struct Node
	{
		int l, r;
		mutable Type val;
		Node(int _l = 0, int _r = 0, Type _val = Type())
		{
			l = _l, r = _r, val = _val;
		}
		friend bool operator<(const Node& a, const Node& b)
		{
			return a.l < b.l;
		}
	};
	/*====================*/
	set<Node>tree;
	/*====================*/
	set<Node>::iterator Split(int pos)//lower
	{
		auto it = tree.lower_bound(Node(pos));
		if (it != tree.end() && it->l == pos)return it;
		--it; int l = it->l, r = it->r, val = it->val;
		tree.erase(it); tree.insert(Node(l, pos - 1, val));
		return tree.insert(Node(pos, r, val)).first;
	}
};

树状数组

权值树状数组

class FenwickTree
{
public:
	int size(void)
	{
		return tree[0];
	}
	void clear(void)
	{
		if (tree != NULL)
		{
			delete[] tree;
			tree = NULL;
		}
	}
	void init(int n)
	{
		this->n = n; m = 0;
		tree = new int[n + 1];
		for (int i = 0; i <= n; ++i)
		{
			tree[i] = 0;
		}
		while ((1 << (m + 1)) <= n)m++;
	}
	bool empty(void)
	{
		return tree[0] == 0;
	}
	void erase(int x)
	{
		tree[0]--;
		while (x <= n)
		{
			tree[x] -= 1;
			x += lowbit(x);
		}
	}
	void insert(int x)
	{
		tree[0]++;
		while (x <= n)
		{
			tree[x] += 1;
			x += lowbit(x);
		}
	}
	~FenwickTree(void)
	{
		clear();
	}
	int operator()(int valu)
	{
		valu--;
		int rank = 0;
		while (valu)
		{
			rank += tree[valu];
			valu -= lowbit(valu);
		}
		return rank + 1;
	}
	int operator[](int rank)
	{
		int sum = 0, valu = 0;
		for (int i = m; i >= 0; --i)
		{
			int temp = valu + (1 << i);
			if (temp <= n && sum + tree[temp] < rank)
			{
				sum += tree[temp]; valu = temp;
			}
		}
		return valu + 1;
	}
private:
	int n = 0, m = 0;
	int* tree = NULL;
	/*====================*/
	int lowbit(int x) { return x & (-x); }
};

一维树状数组

template<class Type>
class FenwickTree
{
public:
	Type ask(int pos)
	{
		Type res = Type();
		while (pos)
		{
			res += tree[pos];
			pos -= lowbit(pos);
		}
		return res;
	}
	void init(int n)
	{
		this->n = n;
		tree = new Type[n + 1];
		for (int i = 0; i <= n; ++i)
		{
			tree[i] = Type();
		}
	}
	~FenwickTree(void)
	{
		delete[] tree;
	}
	void add(int pos, Type d)
	{
		while (pos <= n)
		{
			tree[pos] += d;
			pos += lowbit(pos);
		}
	}
	Type ask(int l, int r)
	{
		Type res = Type(); l--;
		while (r > l)res += tree[r], r -= lowbit(r);
		while (l > r)res -= tree[l], l -= lowbit(l);
		return res;
	}
private:
	int n = 0;
	Type* tree = NULL;
	/*====================*/
	int lowbit(int x) { return x & (-x); }
};

二维树状数组

template<class Type>
class FenwickTree
{
public:
	~FenwickTree(void)
	{
		for (int i = 0; i <= n; ++i)
		{
			delete[] tree[i];
		}
		delete[] tree;
	}
	Type ask(int x, int y)
	{
		Type res = Type();
		while (x)
		{
			int tempy = y;
			while (tempy)
			{
				res += tree[x][tempy];
				tempy -= lowbit(tempy);
			}
			x -= lowbit(x);
		}
		return res;
	}
	void init(int n, int m)
	{
		this->n = n;
		this->m = m;
		tree = new Type * [n + 1];
		for (int i = 0; i <= n; ++i)
		{
			tree[i] = new Type[m + 1];
			for (int j = 0; j <= m; ++j)
			{
				tree[i][j] = Type();
			}
		}
	}
	void add(int x, int y, Type d)
	{
		while (x <= n)
		{
			int tempy = y;
			while (tempy <= m)
			{
				tree[x][tempy] += d;
				tempy += lowbit(tempy);
			}
			x += lowbit(x);
		}
	}
	Type ask(int x1, int y1, int x2, int y2)
	{
		return ask(x2, y2) - ask(x1 - 1, y2) - ask(x2, y1 - 1) + ask(x1 - 1, y1 - 1);
	}
private:
	int n = 0, m = 0;
	Type** tree = NULL;
	/*====================*/
	int lowbit(int x) { return x & (-x); }
};

区间mex

class Range_MEX
{
public:
	Range_MEX(int n, int arr[], int l, int r)
	{
		root = new int[n + 1];
		tree = new Tree[4200000 + 10];

		for (int i = 0; i <= n; ++i)root[i] = -1;

		BuildZero(root[0], l, r);
		for (int i = 1; i <= n; ++i)
		{
			BuildChain(root[i - 1], root[i], i, arr[i]);
		}
	}
	int operator()(int l, int r)
	{
		return Ask(root[r], l);
	}
	~Range_MEX(void)
	{
		delete[] tree;
		delete[] root;
	}
private:
	struct Tree
	{
		int idx;
		int l, r;
		int ls, rs;
		Tree(void)
		{
			idx = 0;
			l = 0, r = 0;
			ls = -1, rs = -1;
		}
	};
	/*====================*/
	int * root;
	Tree* tree; int cnt = -1;
	/*====================*/
	void PushUp(int cur)
	{
		tree[cur].idx = min(tree[tree[cur].ls].idx, tree[tree[cur].rs].idx);
	}
	/*====================*/
	void BuildZero(int& cur, int l, int r)
	{
		if (cur == -1)cur = ++cnt;
		/*====================*/
		tree[cur].l = l, tree[cur].r = r;
		if (l != r)
		{
			int mid = (l + r) >> 1;
			BuildZero(tree[cur].ls, l, mid + 0);
			BuildZero(tree[cur].rs, mid + 1, r);
		}
	}
	void BuildChain(int& pre, int& cur, int idx, int val)
	{
		if (cur == -1)cur = ++cnt;
		/*====================*/
		tree[cur].l = tree[pre].l, tree[cur].r = tree[pre].r;
		tree[cur].ls = tree[pre].ls, tree[cur].rs = tree[pre].rs;
		if (tree[cur].l == tree[cur].r)
		{
			tree[cur].idx = idx;
		}
		else
		{
			int mid = (tree[cur].l + tree[cur].r) >> 1;
			if (val <= mid)BuildChain(tree[pre].ls, tree[cur].ls = -1, idx, val);
			if (mid < val) BuildChain(tree[pre].rs, tree[cur].rs = -1, idx, val);
			PushUp(cur);
		}
	}
	/*====================*/
	int Ask(int& cur, int l)
	{
		if (tree[cur].l == tree[cur].r)return tree[cur].l;
		if (tree[tree[cur].ls].idx < l)return Ask(tree[cur].ls, l);
		if (tree[tree[cur].rs].idx < l)return Ask(tree[cur].rs, l);
		return tree[cur].r + 1;
	}
};

Hash_MAP

const int Base = 19260817;
class Hash_Map 
{
public:
	Hash_Map()
	{
		memset(head, -1, sizeof(head));
		nxt.reserve(1e7);
		key.reserve(1e7);
		val.reserve(1e7);
	}
	lnt& operator[](lnt k)
	{
		int h = hash(k);
		for (int i = head[h]; ~i; i = nxt[i])
		{
			if (key[i] == k)
			{
				return val[i];
			}
		}
		nxt.push_back(head[h]);
		key.push_back(k);
		val.push_back(0);
		head[h] = nxt.size() - 1;
		return val.back();
	}
	lnt has_key(lnt k) 
	{
		int h = hash(k);
		for (int i = head[h]; ~i; i = nxt[i])
		{
			if (key[i] == k)
			{
				return true;
			}
		}
		return false;
	}
private:
	int head[Base];
	vector<int>nxt;
	vector<lnt>key;
	vector<lnt>val;
	int hash(lnt k) 
	{ 
		return k % Base; 
	}
};

线段树合并

Tree* Merge(Tree*& a, Tree*& b)
{
	Tree* cur = NULL;
	if (a == NULL)
	{
		cur = b; b = NULL; return cur;
	}
	if (b == NULL)
	{
		cur = a; a = NULL; return cur;
	}
	cur = new Tree(a->l, b->r);
	if (a->l == b->r)
	{
		//do something
	}
	else
	{
		cur->ls = Merge(a->ls, b->ls);
		cur->rs = Merge(a->rs, b->rs);
	}
	PushUp(cur); delete a; a = NULL; delete b; b = NULL; return cur;
}

李超线段树

class LiChaoTree
{
private:
	struct Function
	{
		int k, b;
		int operator()(int x)
		{
			return k * x + b;
		}
		Function(int _k = 0, int _b = +INF)
		{
			k = _k, b = _b;
		}
	};
	/*====================*/
	struct Node
	{
		Function f;
		Node* ls = NULL;
		Node* rs = NULL;
	};
	/*====================*/
	Node* root = NULL;
	int treel = 0, treer = 0;
	/*====================*/
	void PushDown(Node*& cur, Function f, int treel, int treer)
	{
		if (cur == NULL)cur = new Node;
		int mid = (treel + treer) >> 1;
		if (treel != treer)
		{
			if (cur->f.k < f.k)
			{
				if (f(mid) < cur->f(mid))
				{
					PushDown(cur->rs, cur->f, treel, mid + 0);
				}
				else
				{
					PushDown(cur->ls, f, mid + 1, treer);
				}
			}
			else
			{
				if (f(mid) < cur->f(mid))
				{
					PushDown(cur->ls, cur->f, treel, mid + 0);
				}
				else
				{
					PushDown(cur->rs, f, mid + 1, treer);
				}
			}
		}
		if (f(mid) < cur->f(mid))cur->f = f;
	}
	void Add(Node*& cur, int l, int r, Function f, int treel, int treer)
	{
		if (cur == NULL)cur = new Node;
		if (l <= treel && treer <= r)
		{
			PushDown(cur, f, treel, treer);
		}
		else
		{
			int mid = (treel + treer) >> 1;
			if (l <= mid)Add(cur->ls, l, r, f, treel, mid + 0);
			if (mid < r) Add(cur->rs, l, r, f, mid + 1, treer);
		}
	}
	int Ask(Node*& cur, int x, int treel, int treer)
	{
		int res = +INF;
		if (cur != NULL)
		{
			res = cur->f(x);
			if (treel != treer)
			{
				int mid = (treel + treer) >> 1;
				if (x <= mid)res = min(res, Ask(cur->ls, x, treel, mid + 0));
				if (mid < x) res = min(res, Ask(cur->rs, x, mid + 1, treer));
			}
		}
		return res;
	}
public:
	void init(int treel, int treer)
	{
		this->treel = treel;
		this->treer = treer;
	}
	void operator()(int l, int r, Function  f)
	{
		Add(root, l, r, f, treel, treer);
	}
	int operator[](int x)
	{
		return Ask(root, x, treel, treer);
	}
};

Treap维护珂朵莉树

namespace Treap
{
	struct Node
	{
		Range range;
		int priority;
		int lch, rch;
	}node[N * 4];
	/*====================*/
	int null = -1;
	int root = -1;
	/*====================*/
	int Creat(Range range)
	{
		static int cnt = 0; ++cnt;
		node[cnt].lch = null;
		node[cnt].rch = null;
		node[cnt].priority = rand();
		node[cnt].range = range;
		return cnt;
	}
	/*====================*/
	void PushUp(int cur)
	{
		node[cur].range.L = node[cur].range.l;
		node[cur].range.R = node[cur].range.r;
		node[cur].range.Sum = node[cur].range.sum();
		if (node[cur].lch != null)
		{
			node[cur].range.L = node[node[cur].lch].range.L;
			node[cur].range.Sum += node[node[cur].lch].range.Sum;
		}
		if (node[cur].rch != null)
		{
			node[cur].range.R = node[node[cur].rch].range.R;
			node[cur].range.Sum += node[node[cur].rch].range.Sum;
		}
	}
	void PushDown(int cur)
	{
		if (node[cur].range.lazy != 0)
		{
			if (node[cur].lch != null)
			{
				node[node[cur].lch].range.Maintain(node[cur].range.lazy);
			}
			if (node[cur].rch != null)
			{
				node[node[cur].rch].range.Maintain(node[cur].range.lazy);
			}
			node[cur].range.lazy = 0;
		}
	}
	/*====================*/
	int Merge(int ltree, int rtree)
	{
		if (ltree == null)return rtree;
		if (rtree == null)return ltree;
		PushDown(ltree); PushDown(rtree);
		if (node[ltree].priority < node[rtree].priority)
		{
			node[rtree].lch = Merge(ltree, node[rtree].lch);
			/*======*/PushUp(rtree); return rtree;
		}
		else
		{
			node[ltree].rch = Merge(node[ltree].rch, rtree);
			/*======*/PushUp(ltree); return ltree;
		}
	}
	/*====================*/
	void Lower_Split(int cur, unt index, int& ltree, int& rtree)//index留在rtree
	{
		if (cur == null)
		{
			ltree = rtree = null; return;
		}
		PushDown(cur);
		if (node[cur].range.r < index)
		{
			Lower_Split(node[cur].rch, index, ltree, rtree);
			node[cur].rch = ltree; PushUp(cur); ltree = cur;
		}
		else
		{
			Lower_Split(node[cur].lch, index, ltree, rtree);
			node[cur].lch = rtree; PushUp(cur); rtree = cur;
		}
	}
	void Upper_Split(int cur, unt index, int& ltree, int& rtree)//index留在ltree
	{
		if (cur == null)
		{
			ltree = rtree = null; return;
		}
		PushDown(cur);
		if (node[cur].range.l > index)
		{
			Upper_Split(node[cur].lch, index, ltree, rtree);
			node[cur].lch = rtree; PushUp(cur); rtree = cur;
		}
		else
		{

			Upper_Split(node[cur].rch, index, ltree, rtree);
			node[cur].rch = ltree; PushUp(cur); ltree = cur;
		}
	}
	/*====================*/
	void SplitL(int root, unt index, int& ltree, int& rtree)
	{
		int _temp, _ltree, _mtree, _rtree;
		Upper_Split(root, index, _temp, _rtree);
		Lower_Split(_temp, index, _ltree, _mtree);
		unt l = node[_mtree].range.l;
		unt r = node[_mtree].range.r;
		unt val = node[_mtree].range.val;
		if (l != index)
		{
			ltree = Merge(_ltree, Creat(Range(l, index - 1, val)));
			rtree = Merge(Creat(Range(index + 0, r, val)), _rtree);
		}
		else
		{
			ltree = _ltree;
			rtree = Merge(_mtree, _rtree);
		}
	}
	void SplitR(int root, unt index, int& ltree, int& rtree)
	{
		int _temp, _ltree, _mtree, _rtree;
		Upper_Split(root, index, _temp, _rtree);
		Lower_Split(_temp, index, _ltree, _mtree);
		unt l = node[_mtree].range.l;
		unt r = node[_mtree].range.r;
		unt val = node[_mtree].range.val;
		if (r != index)
		{
			ltree = Merge(_ltree, Creat(Range(l, index + 0, val)));
			rtree = Merge(Creat(Range(index + 1, r, val)), _rtree);
		}
		else
		{
			ltree = Merge(_ltree, _mtree);
			rtree = _rtree;
		}
	}
}

数据类型

大数类

struct Bigint 
{
	int sign; string digits;
	/*====================*/
	Bigint(void) {}
	Bigint(string b) { (*this) = b; }
	Bigint(int b) { (*this) = to_string(b); }
	/*====================*/
	int size(void) 
	{
		return digits.size();
	}
	Bigint inverseSign(void) 
	{ 
		sign *= -1; return (*this);
	}
	Bigint normalize(int newSign) 
	{ 
		for (int i = digits.size() - 1; i > 0 && digits[i] == '0'; i--)
		{
			digits.erase(digits.begin() + i);
		}
		sign = (digits.size() == 1 && digits[0] == '0') ? 1 : newSign; return (*this);
	}
	/*====================*/
	void operator = (string b) 
	{ 
		digits = b[0] == '-' ? b.substr(1) : b;
		reverse(digits.begin(), digits.end());
		this->normalize(b[0] == '-' ? -1 : 1);
	}
	/*====================*/
	bool operator < (const Bigint& b) const 
	{ 
		if (sign != b.sign) return sign < b.sign;
		if (digits.size() != b.digits.size())
			return sign == 1 ? digits.size() < b.digits.size() : digits.size() > b.digits.size();
		for (int i = digits.size() - 1; i >= 0; i--) if (digits[i] != b.digits[i])
			return sign == 1 ? digits[i] < b.digits[i] : digits[i] > b.digits[i];
		return false;
	}
	bool operator == (const Bigint& b) const 
	{
		return digits == b.digits && sign == b.sign;
	}
	/*====================*/
	Bigint operator + (Bigint b) 
	{ 
		if (sign != b.sign) return (*this) - b.inverseSign();
		Bigint c;
		for (int i = 0, carry = 0; i < digits.size() || i < b.size() || carry; i++) {
			carry += (i < digits.size() ? digits[i] - 48 : 0) + (i < b.digits.size() ? b.digits[i] - 48 : 0);
			c.digits += (carry % 10 + 48);
			carry /= 10;
		}
		return c.normalize(sign);
	}
	Bigint operator - (Bigint b) 
	{ 
		if (sign != b.sign) return (*this) + b.inverseSign();
		int s = sign; sign = b.sign = 1;
		if ((*this) < b) return ((b - (*this)).inverseSign()).normalize(-s);
		Bigint c;
		for (int i = 0, borrow = 0; i < digits.size(); i++) {
			borrow = digits[i] - borrow - (i < b.size() ? b.digits[i] : 48);
			c.digits += borrow >= 0 ? borrow + 48 : borrow + 58;
			borrow = borrow >= 0 ? 0 : 1;
		}
		return c.normalize(s);
	}
	Bigint operator * (Bigint b) 
	{ 
		Bigint c("0");
		for (int i = 0, k = digits[i] - 48; i < digits.size(); i++, k = digits[i] - 48) {
			while (k--) c = c + b;
			b.digits.insert(b.digits.begin(), '0');
		}
		return c.normalize(sign * b.sign);
	}
	Bigint operator / (Bigint b) 
	{
		if (b.size() == 1 && b.digits[0] == '0') b.digits[0] /= (b.digits[0] - 48);
		Bigint c("0"), d;
		for (int j = 0; j < digits.size(); j++) d.digits += "0";
		int dSign = sign * b.sign; b.sign = 1;
		for (int i = digits.size() - 1; i >= 0; i--) {
			c.digits.insert(c.digits.begin(), '0');
			c = c + digits.substr(i, 1);
			while (!(c < b)) c = c - b, d.digits[i]++;
		}
		return d.normalize(dSign);
	}
	Bigint operator % (Bigint b) 
	{
		if (b.size() == 1 && b.digits[0] == '0') b.digits[0] /= (b.digits[0] - 48);
		Bigint c("0");
		b.sign = 1;
		for (int i = digits.size() - 1; i >= 0; i--) {
			c.digits.insert(c.digits.begin(), '0');
			c = c + digits.substr(i, 1);
			while (!(c < b)) c = c - b;
		}
		return c.normalize(sign);
	}
	/*====================*/
	friend ostream& operator<<(ostream& output, Bigint& integer)
	{
		if (integer.sign == -1) output << "-";
		for (int i = integer.digits.size() - 1; i >= 0; i--)
		{
			output << integer.digits[i];
		}
		return output;
	}
	friend istream& operator>>(istream& input, Bigint& integer)
	{
		string str; input >> str; integer = str; return input;
	}
};

分数类

class Fraction
{
public:
	Fraction(const Fraction& temp)
	{
		up = temp.up, dw = temp.dw;
	}
	Fraction(int _up = 0, int _dw = 1)
	{
		up = _up, dw = _dw; reduction();
	}

	int upval(void)
	{
		return up;
	}
	int dwval(void)
	{
		return dw;
	}
	double val(void)
	{
		return double(up) / double(dw);
	}

	friend Fraction operator+(const Fraction& a, const Fraction& b)
	{
		Fraction res;
		res.dw = a.dw * b.dw;
		res.up = a.up * b.dw + b.up * a.dw;
		res.reduction(); return res;
	}
	friend Fraction operator-(const Fraction& a, const Fraction& b)
	{
		Fraction res;
		res.dw = a.dw * b.dw;
		res.up = a.up * b.dw - b.up * a.dw;
		res.reduction(); return res;
	}
	friend Fraction operator*(const Fraction& a, const Fraction& b)
	{
		Fraction res;
		res.dw = a.dw * b.dw;
		res.up = a.up * b.up;
		res.reduction(); return res;
	}
	friend Fraction operator/(const Fraction& a, const Fraction& b)
	{
		Fraction res;
		res.dw = a.dw * b.up;
		res.up = a.up * b.dw;
		res.reduction(); return res;
	}

	friend bool operator<(const Fraction& a, const Fraction& b)
	{
		return (a.up * b.dw) < (b.up * a.dw);
	}
	friend bool operator==(const Fraction& a, const Fraction& b)
	{
		return (a.up == b.up) && (a.dw == b.dw);
	}
	friend bool operator>(const Fraction& a, const Fraction& b)
	{
		return (a.up * b.dw) > (b.up * a.dw);
	}
	friend bool operator<=(const Fraction& a, const Fraction& b)
	{
		return !(a > b);
	}
	friend bool operator!=(const Fraction& a, const Fraction& b)
	{
		return !(a == b);
	}
	friend bool operator>=(const Fraction& a, const Fraction& b)
	{
		return !(a < b);
	}

	void operator+=(const Fraction& x)
	{
		up = up * x.dw + x.up * dw;
		dw = dw * x.dw;
		reduction();
	}
	void operator-=(const Fraction& x)
	{
		up = up * x.dw - x.up * dw;
		dw = dw * x.dw;
		reduction();
	}
	void operator*=(const Fraction& x)
	{
		up = up * x.up;
		dw = dw * x.dw;
		reduction();
	}
	void operator/=(const Fraction& x)
	{
		up = up * x.dw;
		dw = dw * x.up;
		reduction();
	}
private:
	int up = 0, dw = 1;
	/*====================*/
	int gcd(int a, int b)
	{
		return b == 0 ? a : gcd(b, a % b);
	}
	/*====================*/
	void reduction(void)
	{
		int divisor = gcd(up, dw);
		if (divisor != 0)
		{
			up /= divisor, dw /= divisor;
			if (dw < 0)dw *= -1, up *= -1;
		}
	}
};

模数类

class Modulo
{
public:
	int val(void)
	{
		return num;
	}

	Modulo(int x = 0)
	{
		num = x % MOD;
	}
	Modulo(const Modulo& temp)
	{
		num = temp.num;
	}

	friend Modulo operator+(const Modulo& a, const Modulo& b)
	{
		Modulo res;
		res.num = (a.num + b.num) % res.MOD;
		return res;
	}
	friend Modulo operator-(const Modulo& a, const Modulo& b)
	{
		Modulo res;
		res.num = (a.num - b.num + res.MOD) % res.MOD;
		return res;
	}
	friend Modulo operator*(const Modulo& a, const Modulo& b)
	{
		Modulo res;
		res.num = (a.num * b.num) % res.MOD;
		return res;
	}
	friend Modulo operator/(const Modulo& a, const Modulo& b)
	{
		Modulo res;
		res.num = (a.num * res.inv(b.num)) % res.MOD;
		return res;
	}

	friend bool operator< (const Modulo& a, const Modulo& b)
	{
		return a.num < b.num;
	}
	friend bool operator==(const Modulo& a, const Modulo& b)
	{
		return a.num == b.num;
	}
	friend bool operator> (const Modulo& a, const Modulo& b)
	{
		return a.num > b.num;
	}
	friend bool operator<=(const Modulo& a, const Modulo& b)
	{
		return a.num <= b.num;
	}
	friend bool operator!=(const Modulo& a, const Modulo& b)
	{
		return a.num != b.num;
	}
	friend bool operator>=(const Modulo& a, const Modulo& b)
	{
		return a.num >= b.num;
	}

	void operator+=(const Modulo& x)
	{
		num = (num + x.num) % MOD;
	}
	void operator-=(const Modulo& x)
	{
		num = (num - x.num + MOD) % MOD;
	}
	void operator*=(const Modulo& x)
	{
		num = (num * x.num) % MOD;
	}
	void operator/=(const Modulo& x)
	{
		num = (num * inv(x.num)) % MOD;
	}
private:
	int num = 0;
	const int MOD = 998244353;
	/*====================*/
	int inv(int x)
	{
		return Pow(x, MOD - 2);
	}
	int Pow(int a, int b)
	{
		int res = 1;
		while (b)
		{
			if (b & 1)
			{
				res = (res * a) % MOD;
			}
			b >>= 1, a = (a * a) % MOD;
		}
		return res;
	}
};

标签:node,5.20240330,return,cur,val,int,v1.10,void,模板
From: https://www.cnblogs.com/ProtectEMmm/p/18105897

相关文章

  • 多态在模板类中的应用
    先看一个多态的例子:classHuman{public:virtualvoideat=0;virtual~Human(){}};classMen:publicHuman{public:virtualvoideat(){cout<<"男人"<<endl;}};classWomen:publicHuman{public:virtu......
  • helm 安装 nginx-ingress-controller v1.10.0
    1、说明准备nginx-ingress三种不同的部署模式Deployment+LoadBalancer采用deployment进行部署nginx-ingress-controller,需要创建一个type:LoadBalancer的service进行关联nginx-ingress-controller这组pod。通常是在使用公有云进行创建负载均衡器并绑定公网地址。只要将域名......
  • 帝国cms自适应html5古诗词历史名句书籍文章资讯网站源码整站模板sinfo插件带采集会员
    (购买本专栏可免费下载栏目内所有资源不受限制,持续发布中,需要注意的是,本专栏为批量下载专用,并无法保证某款源码或者插件绝对可用,介意不要购买!购买本专栏住如有什么源码需要,可向博主私信,第二天即可发布!博主有几万资源)帝国cms自适应html5古诗词名句书籍文章资讯网站源码整站模板s......
  • 并查集模板
    目录并查集的存储结构并查集查询路径压缩并查集合并合并优化--启发式优化合并优化--按秩合并可撤销并查集算法原理重要操作实现并查集是一种巧妙优雅的数据结构,主要用于解决元素分组和不相交集合的合并和查询问题。并查集是大量的树(单个节点也算是树)经过合并生成一......
  • [web]: HTML 测试模板
    [web]: HTML 测试模板    一、HTML 测试模板内容 <!DOCTYPEhtml><html><head><metacharset="utf-8"><title>测试模板</title><scriptsrc="https://code.jquery.com/jquery-3.7.1.min.js"></script&g......
  • 类模板、函数模板、其他
    类模板、函数模板、其他static示例代码:#ifndef__COMPLEX__#define__COMPLEX__​classcomplex{  //成员函数的隐藏参数有this->形参不能写.返回值当中可以写可以不写  public: doublereal()const{returnthis->re;}  private: doubler......
  • [题解]P1439 【模板】最长公共子序列
    P1439【模板】最长公共子序列题意简述给出\(1,2,…,n\)的两个排列\(P_1\)和\(P_2\),求它们的最长公共子序列。范围限制:\(n\le10^5\)。样例53214512345输出:3。思路简述这道题看似是最长公共子序列,但是发现如果用\(O(n^2)\)的复杂度实现\(LCS\)就会时......
  • yii2 Gii使用和自定义模板
    yii2Gii使用和自定义模板配置开启giiconfig/web.php添加代码if(YII_ENV_DEV){$config['bootstrap'][]='gii';$config['modules']['gii']=['class'=>'yii\gii\Module',];}入口脚本web......
  • 软件项目管理(开发/实施/运维/安全/交付)全套文档模板
      前言:在软件项目管理中,每个阶段都有其特定的目标和活动,确保项目的顺利进行和最终的成功交付。以下是软件项目管理各个阶段的详细资料:软件项目全套文档资料下载:点我获取1.需求阶段目标:收集、分析和定义用户需求和业务目标。主要活动:需求调研:与用户沟通,了解他们的需求......
  • delphi ORM和泛型模板
    delphiORM和泛型模板实现CRUD1)定义数据模型(data-model)数据模型是ORM数据序列/还原所必需的。TTable<T:record>=record//1个表rows:TArray<T>;//表的行end;TTable2<T,T2:record>=record//2个表table1:TTable<T>;......