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

算法模板 v1.9.1.20240303

时间:2024-03-03 16:13:22浏览次数:26  
标签:node return cur val int void v1.9 1.20240303 模板

算法模板

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级祖先”。

目录

编译

#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
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;
		}
	};
	/*====================*/
	int cur[N];//当前弧优化
	int n, m, s, t;//点,边,源,汇
	vector<int>G[N];//邻接表
	int d[N], vis[N];//图分层
	Edge edge[2 * M]; int cnt;//边
	/*====================*/
	int AddEdge(int u, int v, int c)
	{
		edge[m++] = Edge(u, v, c, 0);
		edge[m++] = Edge(v, u, 0, 0);
		G[u].push_back(m - 2);
		G[v].push_back(m - 1);
		return m - 2;
	}
	/*====================*/
	bool BFS(void)
	{
		for (int i = 0; i <= n; ++i)
		{
			d[i] = vis[i] = 0;
		}
		queue<int>q; q.push(s);
		d[s] = 0; vis[s] = 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.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;
	}
	int MaxFlow(void)
	{
		int flow = 0;
		while (BFS())
		{
			flow += DFS(s, INF);
			for (int i = 1; i <= n; ++i)
			{
				cur[i] = 0;
			}
		}
		return flow;
	}
	/*====================*/
	void Init(void)
	{
		for (int i = 1; i <= n; ++i)
		{
			G[i].clear();
		}
		m = 0; n = 0; s = ++n, t = ++n;
	}
}
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费用流
namespace _ZKW
{
	const int N = 1e5 + 10;
	const int M = 1e5 + 10;
	/*====================*/
	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, m, s, t;
	vector<int>G[N];
	int mincost, maxflow;
	int dep[N];	bool vis[N];
	Edge edge[2 * M]; int cnt;
	/*====================*/
	void AddEdge(int u, int v, int c, int w)
	{
		edge[cnt++] = Edge(u, v, c, +w);
		edge[cnt++] = Edge(v, u, 0, -w);
		G[u].push_back(cnt - 2);
		G[v].push_back(cnt - 1);
	}
	/*====================*/
	bool SPFA(void)
	{
		for (int i = 1; i <= n; ++i)
		{
			vis[i] = false, dep[i] = INF;
		}
		vis[t] = true, dep[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() && dep[q.front()] > dep[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 && dep[e1.v] > dep[x] - e1.w)
				{
					dep[e1.v] = dep[x] - e1.w;
					if (!vis[e1.v])
					{
						vis[e1.v] = true;
						if (!q.empty() && dep[e1.v] < dep[q.front()])
						{
							q.push_front(e1.v);
						}
						else
						{
							q.push_back(e1.v);
						}
					}
				}
			}
		}
		return dep[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 (dep[x] - e1.w == dep[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;
	}
	int MinCost(void)
	{
		while (SPFA())
		{
			vis[t] = true;
			while (vis[t])
			{
				for (int i = 1; i <= n; ++i)
				{
					vis[i] = false;
				}
				maxflow += DFS(s, INF);
			}
		}
		return mincost;
	}
	/*====================*/
	int Init(void)
	{
		cin >> n >> m >> s >> t;
		mincost = maxflow = cnt = 0;
		for (int i = 1; i <= n; ++i)
		{
			G[i].clear();
		}
		for (int i = 1; i <= m; ++i)
		{
			int u, v, c, w;
			cin >> u >> v >> c >> w;
			AddEdge(u, v, c, w);
		}
		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);
			}
		}
	}
}

随机化

模拟退火

#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 Heap
{
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);
	}
private:
	priority_queue<Type>heap1;
	priority_queue<Type>heap2;
};

并查集

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;
}

李超线段树

const int N = 4e4 + 10;
const double INF = 1e9;
/*====================*/
typedef long long ll;
/*====================*/
struct Function
{
	int id;
	double k, b;
	int gcd(int a, int b)
	{
		return b == 0 ? a : gcd(b, a % b);
	}
	double operator()(double x)
	{
		return k * x + b;
	}
	Function(int _id = 0, int x1 = 1, int x2 = 2, int y1 = 1, int y2 = 2)
	{
		id = _id;
		if (x1 == x2)
		{
			k = 0, b = max(y1, y2);
		}
		else
		{
			int d = gcd(abs(y1 - y2), abs(x1 - x2));
			double dy = (y1 - y2) / d;
			double dx = (x1 - x2) / d;
			k = dy / dx; b = y1 - k * x1;
		}
	}
};
/*====================*/
struct Node
{
	Function f;
	int l = 0, r = 0;
};
/*====================*/
int idx[N];
Node node[N << 2];
/*====================*/
int ls(int p)
{
	return p << 1;
}
int rs(int p)
{
	return p << 1 | 1;
}
void Build(int p, int l, int r)
{
	node[p].l = l, node[p].r = r;
	if (node[p].l == node[p].r)
	{
		idx[l] = p; return;
	}
	else
	{
		int mid = (node[p].l + node[p].r) >> 1;
		Build(ls(p), l, mid + 0);
		Build(rs(p), mid + 1, r);
	}
}
void PushDown(int p, Function f)
{
	if (node[p].f.id == 0)
	{
		node[p].f = f;
	}
	else
	{
		int l = node[p].l, r = node[p].r;
		int x = (node[p].l + node[p].r) >> 1;
		if (l == r)
		{
			if (node[p].f(x) < f(x))
			{
				node[p].f = f;
			}
			else if (node[p].f(x) == f(x))
			{
				if (node[p].f.id > f.id)
				{
					node[p].f = f;
				}
			}
		}
		else
		{
			if (node[p].f.k < f.k)
			{
				if (node[p].f(x) < f(x))
				{
					PushDown(ls(p), node[p].f); node[p].f = f;
				}
				else if (node[p].f(x) == f(x))
				{
					PushDown(rs(p), f);
				}
				else if (node[p].f(x) > f(x))
				{
					PushDown(rs(p), f);
				}
			}
			else if (node[p].f.k == f.k)
			{
				if (node[p].f.b < f.b)
				{
					node[p].f = f;
				}
				else if (node[p].f.b == f.b)
				{
					if (node[p].f.id > f.id)
					{
						node[p].f = f;
					}
				}
			}
			else if (node[p].f.k > f.k)
			{
				if (node[p].f(x) < f(x))
				{
					PushDown(rs(p), node[p].f); node[p].f = f;
				}
				else if (node[p].f(x) == f(x))
				{
					PushDown(ls(p), f);
				}
				else if (node[p].f(x) > f(x))
				{
					PushDown(ls(p), f);
				}
			}
		}
	}
}
void Add(int p, int l, int r, Function f)
{
	if (l <= node[p].l && node[p].r <= r)
	{
		PushDown(p, f);
	}
	else
	{
		int mid = (node[p].l + node[p].r) >> 1;
		if (l <= mid)Add(ls(p), l, r, f);
		if (mid < r) Add(rs(p), l, r, f);
	}
}
void Ask(int p, int x, double fx, int &id)
{
	if (node[p].f.id != 0)
	{
		if (node[p].f(x) == fx)
		{
			if (node[p].f.id < id)
			{
				id = node[p].f.id;
			}
		}
		else if (node[p].f(x) > fx)
		{
			fx = node[p].f(x);
			id = node[p].f.id;
		}
	}
	if (node[p].l != node[p].r)
	{
		int mid = (node[p].l + node[p].r) >> 1;
		if (x <= mid)Ask(ls(p), x, fx, id);
		if (mid < x) Ask(rs(p), x, fx, id);
	}
}
/*====================*/
int main()
{
	int n; cin >> n;
	int lastans = 0;
	Build(1, 1, MODX + 10);
	for (int i = 1; i <= n; ++i)
	{
		int op; cin >> op;
		if (op == 1)
		{
			static int id = 0;
			int x0, y0, x1, y1;
			cin >> x0 >> y0 >> x1 >> y1;
			x0 = (x0 + lastans - 1) % MODX + 1;
			x1 = (x1 + lastans - 1) % MODX + 1;
			y0 = (y0 + lastans - 1) % MODY + 1;
			y1 = (y1 + lastans - 1) % MODY + 1;
			Add(1, min(x0, x1), max(x0, x1), Function(++id, x0, x1, y0, y1));
		}
		else
		{
			int x; cin >> x; x = (x + lastans - 1) % MODX + 1;
			lastans = 0; Ask(1, x, -INF, lastans);
			cout << lastans << endl;
		}
	}
	return 0;
}

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,return,cur,val,int,void,v1.9,1.20240303,模板
From: https://www.cnblogs.com/ProtectEMmm/p/18050165

相关文章

  • 并查集(模板介绍+路径压缩)
    并查集(模板介绍+路径压缩)题面P3367并查集题目描述如题,现在有一个并查集,你需要完成合并和查询操作。第一行包含两个整数N,M,表示共有N个元素和M个操作。接下来M行,每行包含三个整数Z,X,Y。当Z=1时,将X与Y所在的集合合并。当Z=2时,输出Z与Y是否在同一集合内,是的输出Y;否则输出N......
  • st表+lca模板
    st表#include<bits/stdc++.h>#definelllonglong#definefd(i,a,b)for(inti=a;i<=b;++i)usingnamespacestd;lln,m,t,l,r,dp[1000100][100];intmain(){ std::ios::sync_with_stdio(false); cin>>m>>n; fd(i,1,m)cin>>dp[i][0]; ......
  • 树状数组模板
    单修区查【模板】树状数组1题目描述如题,已知一个数列,你需要进行下面两种操作:将某一个数加上$x$求出某区间每一个数的和输入格式第一行包含两个正整数$n,m$,分别表示该数列数字的个数和操作的总个数。第二行包含$n$个用空格分隔的整数,其中第$i$个数字表示数列......
  • Vue 3.0 模板语法
    Vue.js使用了基于HTML的模板语法,允许开发者声明式地将DOM绑定至底层组件实例的数据。所有Vue.js的模板都是合法的HTML,所以能被遵循规范的浏览器和HTML解析器解析。在底层的实现上,Vue将模板编译成虚拟DOM渲染函数。结合响应性系统,Vue能够智能地计算出最少需要重新渲......
  • SiteServer CMS远程模板下载getshell漏洞导致的黑SEO利用分析溯源
    前言某日中午,涉及一代理商客户网站发现异常SQ内容,要求进行溯源分析并找出根本原因。0x01初步分析通过提供的链接(www.xxx.com.cn/2023j19tPLKn2/55151),确认涉及黑帽SEO活动,通过百度搜索进一步验证也证实了这一点。0x02日志分析黑客常常在植入菠菜或非法广告的网站中设置后......
  • 模板记录
    RMQ求Lca怕考场被卡,所以临省选重新复习一下。有个性质:若\(u,v\)不成祖先和儿子关系,则\(u,v\)的\(lca\)的\(dfs\)序一定不在\(dfn_u\)到\(dfn_v\)之间,所以我们只用找到\(dfn_u\)到\(dfn_v\)之间深度最小点\(d\)的就行了,\(d\)的父亲显然是\(u,v\)的\(lca\)......
  • Flask新手四件套、session、转换器、取数据与模板语法
    新手四件套(返回格式)#导入fromflaskimportFlask,request,render_template,redirect,session#返回字符串return'字符串'#返回模板returnrender_template('模板名字')#传参returnrender_template('模板名字',key=value)#返回重定向returnredirect('/......
  • IDEA Alibaba规范化模板(代码格式化,注释模板化)
    格式化配置阿里模板下载地址:https://github.com/alibaba/p3c/tree/master/p3c-formatter下载下来的文件是针对ecplice的,在IDEA中使用配置文件,需要安装EclipseCodeFormatter插件,安装如下配置格式化模板方式如下注释模板配置修改模板处如下以一下模板修改class、interfa......
  • Vue 2x 系列之(三)模板语法
    模板语法容器里的代码被称为【Vue模板】,模板语法就是指模板的代码中可以写哪些Vue语法【类似:{{name}}】插值语法:把指定的值放在指定的位置。插值语法往往用于指定标签体内容。指令语法:Vue指令所在的属性值会作为JavaScript表达式执行v-bind:用于给标签中的任意一个属性动态的......
  • 【模板】任意模数多项式乘法
    题目描述给定\(2\)个多项式\(F(x),G(x)\),请求出\(F(x)\timesG(x)\)。系数对\(p\)取模,且不保证\(p\)可以分解成\(p=a\cdot2^k+1\)之形式。题解可以用快速数论变换NTT算法,关键在于取的那个素数。由于系数最大为\(10^5\times10^{9+9}=10^{23}\)所以可以......