zoukankan      html  css  js  c++  java
  • 模板复习

    没几天就要退役了(QAQ),赶紧复习下板子。
    慢慢补

    高精

    不久前打过,传送门

    数学、数论

    • 线性筛
      模板传送门
      模板题仅筛素数。这里包括筛欧拉函数。
    #include<cstdio>
    using namespace std;
    const int N = 1e7 + 10;
    int pr[N >> 2];
    bool v[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    int main()
    {
    	int i, j, n, m, l = 0;
    	n = re();
    	m = re();
    	v[0] = v[1] = 1;
    	for (i = 2; i <= n; i++)
    	{
    		if (!v[i])
    			pr[++l] = i;
    		for (j = 1; j <= l; j++)
    		{
    			if (i * pr[j] > n)
    				break;
    			v[i * pr[j]] = 1;
    			if (!(i % pr[j]))
    				break;
    		}
    	}
    	for (i = 1; i <= m; i++)
    		v[re()] ? printf("No
    ") : printf("Yes
    ");
    	return 0;
    }
    \筛欧拉函数
    #include<cstdio>
    using namespace std;
    const int N = 1e7 + 10;
    int pr[N >> 2], phi[N];
    bool v[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    int main()
    {
    	int i, j, n, m, l = 0;
    	n = re(); m = re();
    	v[0] = v[1] = phi[1] = 1;
    	for (i = 2; i < n; i++)
    	{
    		if (!v[i])
    			pr[++l] = i, phi[i] = i - 1;
    		for (j = 1; j <= l; j++)
    		{
    			if (i * pr[j] > n)
    				break;
    			v[i * pr[j]] = 1;
    			phi[i * pr[j]] = phi[i] * (pr[j] - 1);
    			if (!(i % pr[j]))
    			{
    				phi[i * pr[j]] = phi[i] * pr[j];
    				break;
    			}
    		}
    	}
    	for (i = 1; i <= m; i++)
    		printf("%d
    ", phi[re()]);
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    int mod;
    inline int ksm(int x, int y)
    {
    	int s = 1;
    	for (; y; y >>= 1, x = 1LL * x * x % mod)
    		if (y & 1)
    			s = 1LL * s * x % mod;
    	return s % mod;
    }
    int main()
    {
    	int x, y;
    	scanf("%d%d%d", &x, &y, &mod);
    	printf("%d^%d mod %d=%d", x, y, mod, ksm(x, y));
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    const int N = 3e6 + 10;
    int inv[N];
    int main()
    {
    	int i, n, mod;
    	scanf("%d%d", &n, &mod);
    	for (printf("%d
    ", inv[1] = 1), i = 2; i <= n; i++)
    		printf("%d
    ", inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod);
    	return 0;
    }
    
    • 扩展欧几里得
    一直不太会这玩意,不会推又记不住结论。。只好在这写一遍结论了。 求方程$ax + by = c$的解$x, y$,设$d = gcd(a, b)$,那么方程有解仅当$d | c$。 先用$exgcd$求出$ax + by = d$的特解$x_0, y_0$,那么原方程的特解为$frac{c}{d} imes x_0, frac{c}{d} imes y_0$。 而通解为$x = frac{c}{d} imes x_0 + k imes frac{b}{d}, y = frac{c}{d} imes y_0 - k imes frac{a}{d}, (k in mathbb{Z})$。 求线性同余方程$a imes x equiv b (mod m)$的解。 设$a imes x - b$为$m$的$-y$倍,那么方程转化为$a imes x + m imes y = b$,于是同样可以和上面一样解出特解$x_0$,那么原方程的一个解为$x_0 imes frac{b}{gcd(a, m)}$,通解为所有模$frac{m}{gcd(a, m)}$与$x$同余的整数。 [模板传送门](https://www.luogu.org/problemnew/show/P1082) 并没有找到什么好的模板,只好用这道$NOIP$充数了,主要是记录$exgcd$。
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    ll exgcd(ll a, ll b, ll &x, ll &y)
    {
    	if (!b)
    	{
    		x = 1; y = 0;
    		return a;
    	}
    	ll gcd = exgcd(b, a % b, x, y), z = x;
    	x = y; y = z - a / b * y;
    	return gcd;
    }
    int main()
    {
    	ll a, b, x, y;
    	scanf("%lld%lld", &a, &b);
    	exgcd(a, b, x, y);
    	printf("%lld", (x + b) % b);
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    const int N = 1e5 + 10;
    int fac[N], inv[N], mod;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    long long C(int x, int y)
    {
    	if (x < y)
    		return 0;
    	if (!y || !(x ^ y))
    		return 1;
    	if (x < mod && y < mod)
    		return 1LL * fac[x] * inv[fac[y]] % mod * inv[fac[x - y]] % mod;
    	return 1LL * C(x % mod, y % mod) * C(x / mod, y / mod) % mod;
    }
    int main()
    {
    	int i, n, m, T;
    	T = re();
    	while (T--)
    	{
    		n = re(); m = re(); mod = re();
    		fac[1] = inv[1] = 1;
    		for (i = 2; i <= mod; i++)
    			fac[i] = 1LL * fac[i - 1] * i % mod, inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
    		printf("%lld
    ", C(n + m, m));
    	}
    	return 0;
    }
    

    (ST)

    模板传送门
    求的是最大值。

    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int N = 1e5 + 10;
    int f[N][18], L[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline int maxn(int x, int y){ return x > y ? x : y; }
    int main()
    {
    	int i, j, n, m, k, x, y;
    	n = re();
    	m = re();
    	for (i = 1; i <= n; i++)
    	{
    		f[i][0] = re();
    		L[i] = log2(i);
    	}
    	for (j = 1; j <= L[n]; j++)
    		for (i = 1; i + (1 << j) - 1 <= n; i++)
    			f[i][j] = maxn(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
    	for (i = 1; i <= m; i++)
    	{
    		x = re();
    		y = re();
    		k = L[y - x + 1];
    		printf("%d
    ", maxn(f[x][k], f[y - (1 << k) + 1][k]));
    	}
    	return 0;
    }
    

    数据结构

    #include<cstdio>
    using namespace std;
    const int N = 1e4 + 10;
    int fa[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    int fin(int x)
    {
    	if (!(fa[x] ^ x))
    		return x;
    	return fa[x] = fin(fa[x]);
    }
    int main()
    {
    	int i, n, m, x, y, p;
    	n = re();
    	m = re();
    	for (i = 1; i <= n; i++)
    		fa[i] = i;
    	for (i = 1; i <= m; i++)
    	{
    		p = re();
    		x = re();
    		y = re();
    		if (p ^ 1)
    			fin(x) ^ fin(y) ? printf("N
    ") : printf("Y
    ");
    		else
    		{
    			x = fin(x);
    			y = fin(y);
    			if (x ^ y)
    				fa[x] = y;
    		}
    	}
    	return 0;
    }
    
    • 堆(二叉堆,STL优先队列)
      只会用STL
      模板传送门
    #include<cstdio>
    #include<queue>
    #include<vector>
    using namespace std;
    priority_queue<int, vector<int>, greater<int> >q;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    int main()
    {
    	int i, n, p;
    	n = re();
    	for (i = 1; i <= n; i++)
    	{
    		p = re();
    		if (p ^ 1)
    		{
    			if (p ^ 2)
    				q.pop();
    			else
    				printf("%d
    ", q.top());
    		}
    		else
    			q.push(re());
    	}
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 10;
    int sta[N], wid[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline ll maxn(ll x, ll y) { return x > y ? x : y; }
    int main()
    {
    	int i, top, n, x, L;
    	ll ma;
    	while (n = re())
    	{
    		for (i = 1, top = ma = 0; i <= n + 1; i++)
    		{
    			x = (i ^ (n + 1) ? re() : 0);
    			if (sta[top] <= x)
    				sta[++top] = x, wid[top] = 1;
    			else
    			{
    				for (L = 0; sta[top] > x; top--)
    					L += wid[top], ma = maxn(ma, 1LL * L * sta[top]);
    				sta[++top] = x; wid[top] = L + 1;
    			}
    		}
    		printf("%lld
    ", ma);
    	}
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    const int N = 1e6 + 10;
    int qma[N], qmi[N], a[N], ans[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline int maxn(int x, int y) { return x > y ? x : y; }
    inline int minn(int x, int y) { return x < y ? x : y; }
    int main()
    {
    	int i, n, m, lma = 1, rma = 0, lmi = 1, rmi = 0;
    	n = re(); m = re();
    	for (i = 1; i <= n; i++)
    		a[i] = re();
    	for (i = 1; i < m; i++)
    	{
    		for (; lma <= rma && a[qma[rma]] <= a[i]; rma--);
    		for (; lmi <= rmi && a[qmi[rmi]] >= a[i]; rmi--);
    		qma[++rma] = qmi[++rmi] = i;
    	}
    	for (i = m; i <= n; i++)
    	{
    		for (; lma <= rma && i - qma[lma] + 1 > m; lma++);
    		for (; lmi <= rmi && i - qmi[lmi] + 1 > m; lmi++);
    		for (; lma <= rma && a[qma[rma]] <= a[i]; rma--);
    		for (; lmi <= rmi && a[qmi[rmi]] >= a[i]; rmi--);
    		qma[++rma] = qmi[++rmi] = i;
    		printf("%d ", a[qmi[lmi]]); ans[i] = a[qma[lma]];
    	}
    	for (i = m, printf("
    "); i <= n; i++)
    		printf("%d ", ans[i]);
    	return 0;
    }
    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef unsigned long long ull;
    const int N = 1e4 + 10;
    const int base = 1331;
    ull a[N];
    inline ull re_l()
    {
    	ull x = 0;
    	char c = getchar();
    	for (; (c < '0' || c > '9') && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z'); c = getchar());
    	for (; (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); c = getchar())
    		x = x * base + c;
    	return x;
    }
    int main()
    {
    	int i, n, s = 0;
    	scanf("%d", &n);
    	for (i = 1; i <= n; i++)
    		a[i] = re_l();
    	sort(a + 1, a + n + 1);
    	for (i = 1; i <= n; i++)
    		if (a[i] ^ a[i - 1] || !(i ^ 1))
    			s++;
    	printf("%d", s);
    	return 0;
    }
    
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 1e6 + 10;
    int nex[N], f[N];
    char a[N], b[N];
    int main()
    {
    	int i, j, n, m;
    	scanf("%s%s", a + 1, b + 1);
    	n = strlen(a + 1); m = strlen(b + 1);
    	for (i = 2, j = 0; i <= m; i++)
    	{
    		for (; j && b[i] != b[j + 1]; j = nex[j]);
    		nex[i] = (b[i] == b[j + 1] ? ++j : j);
    	}
    	for (i = 1, j = 0; i <= n; i++)
    	{
    		for (; j && (!(j ^ n) || a[i] != b[j + 1]); j = nex[j]);
    		f[i] = (a[i] == b[j + 1] ? ++j : j);
    		if (!(j ^ m))
    			printf("%d
    ", i - j + 1);
    	}
    	for (i = 1; i <= m; i++)
    		printf("%d ", nex[i]);
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    const int N = 5e5 + 10;
    int trie[N][30], a[55], l, po = 1;
    bool v[N], ed[N];
    inline void re_l()
    {
    	char c = getchar();
    	for (; c < 'a' || c > 'z'; c = getchar());
    	for (l = 0; c >= 'a' && c <= 'z'; c = getchar())
    		a[++l] = c - 'a' + 1;
    }
    inline void ins()
    {
    	int i, nw = 1;
    	for (i = 1; i <= l; i++)
    		nw = (trie[nw][a[i]] ? trie[nw][a[i]] : trie[nw][a[i]] = ++po);
    	ed[nw] = 1;
    }
    inline int fin()
    {
    	int i, nw = 1;
    	for (i = 1; i <= l && nw; i++)
    		nw = trie[nw][a[i]];
    	if (!nw || !ed[nw]) return 0;
    	return v[nw] ? 2 : v[nw] = 1;
    }
    int main()
    {
    	int i, n, m, x;
    	scanf("%d", &n);
    	for (i = 1; i <= n; i++)
    		re_l(), ins();
    	scanf("%d", &m);
    	for (i = 1; i <= m; i++)
    		re_l(), x = fin(), (x ? (x ^ 1 ? printf("REPEAT
    ") : printf("OK
    ")) : printf("WRONG
    "));
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    const int N = 5e5 + 10;
    int C[N], n;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline int lowbit(int x) { return x & -x; }
    inline void add(int x, int y) { for (; x <= n; x += lowbit(x)) C[x] += y; }
    inline int ask(int x)
    {
    	int s = 0;
    	for (; x; x -= lowbit(x))
    		s += C[x];
    	return s;
    }
    int main()
    {
    	int i, m, p, x, y;
    	n = re(); m = re();
    	for (i = 1; i <= n; i++)
    		add(i, re());
    	for (i = 1; i <= m; i++)
    	{
    		p = re() - 1; x = re(); y = re();
    		p ? (void)printf("%d
    ", ask(y) - ask(x - 1)) : add(x, y);
    	}
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 10;
    ll S[N << 2], a[N], ad[N << 2];
    inline ll re()
    {
    	ll x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    void pp(int r){ S[r] = S[r << 1] + S[r << 1 | 1]; }
    void pn(int r, int x, int y)
    {
    	ll &k = ad[r];
    	if (k)
    	{
    		int lx = r << 1, ly = r << 1 | 1, mid = (x + y) >> 1;
    		ad[lx] += k;
    		ad[ly] += k;
    		S[lx] += k * (mid - x + 1);
    		S[ly] += k * (y - mid);
    		k = 0;
    	}
    }
    void bu(int r, int x, int y)
    {
    	if (!(x ^ y))
    		S[r] = a[x];
    	else
    	{
    		int mid = (x + y) >> 1;
    		bu(r << 1, x, mid);
    		bu(r << 1 | 1, mid + 1, y);
    		pp(r);
    	}
    }
    void upd(int r, int x, int y, int ql, int qr, ll k)
    {
    	if (ql <= x && y <= qr)
    	{
    		S[r] += k * (y - x + 1);
    		ad[r] += k;
    		return;
    	}
    	int mid = (x + y) >> 1;
    	pn(r, x, y);
    	if (ql <= mid)
    		upd(r << 1, x, mid, ql, qr, k);
    	if (mid < qr)
    		upd(r << 1 | 1, mid + 1, y, ql, qr, k);
    	pp(r);
    }
    ll qu(int r, int x, int y, int ql, int qr)
    {
    	if (ql <= x && y <= qr)
    		return S[r];
    	int mid = (x + y) >> 1;
    	ll s = 0;
    	pn(r, x, y);
    	if (ql <= mid)
    		s += qu(r << 1, x, mid, ql, qr);
    	if (mid < qr)
    		s += qu(r << 1 | 1, mid + 1, y, ql, qr);
    	return s;
    }
    int main()
    {
    	int i, n, m, x, y, p;
    	n = re();
    	m = re();
    	for (i = 1; i <= n; i++)
    		a[i] = re();
    	bu(1, 1, n);
    	for (i = 1; i <= m; i++)
    	{
    		p = re();
    		x = re();
    		y = re();
    		if (p ^ 2)
    			upd(1, 1, n, x, y, re());
    		else
    			printf("%lld
    ", qu(1, 1, n, x, y));
    	}
    	return 0;
    }
    
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 10;
    const int M = 350;
    ll a[N], S[M], ad[M];
    int L[N], R[N], pos[N];
    inline ll re()
    {
    	ll x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    void modify(int x, int y, ll k)
    {
    	int l = pos[x], r = pos[y], i;
    	if (!(l ^ r))
    	{
    		for (i = x; i <= y; i++)
    			a[i] += k;
    		S[l] += k * (y - x + 1);
    		return;
    	}
    	for (i = x; i <= R[l]; i++)
    		a[i] += k;
    	S[l] += k * (R[l] - x + 1);
    	for (i = l + 1; i < r; i++)
    		ad[i] += k;
    	for (i = L[r]; i <= y; i++)
    		a[i] += k;
    	S[r] += k * (y - L[r] + 1);
    }
    ll qu(int x, int y)
    {
    	int l = pos[x], r = pos[y], i;
    	ll s = 0;
    	if (!(l ^ r))
    	{
    		for (i = x; i <= y; i++)
    			s += a[i];
    		return s + ad[l] * (y - x + 1);
    	}
    	for (i = x; i <= R[l]; i++)
    		s += a[i];
    	s += ad[l] * (R[l] - x + 1);
    	for (i = l + 1; i < r; i++)
    		s += S[i] + ad[i] * (R[i] - L[i] + 1);
    	for (i = L[r]; i <= y; i++)
    		s += a[i];
    	return s + ad[r] * (y - L[r] + 1);
    }
    int main()
    {
    	int i, j, n, m, x, y, p, k;
    	n = re(); m = re(); k = sqrt(n);
    	for (i = 1; i <= n; i++)
    		a[i] = re();
    	for (i = 1; i <= k; i++)
    		L[i] = (i - 1) * k + 1, R[i] = i * k;
    	if (R[k] < n)
    		L[k + 1] = R[k] + 1, R[++k] = n;
    	for (i = 1; i <= k; i++)
    		for (j = L[i]; j <= R[i]; j++)
    			S[i] += a[j], pos[j] = i;
    	for (i = 1; i <= m; i++)
    	{
    		p = re() - 1; x = re(); y = re();
    		p ? (void)printf("%lld
    ", qu(x, y)) : modify(x, y, re());
    	}
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    const int N = 1e5 + 10;
    struct sp {
    	int so[2], s, v, si, fa;
    };
    sp tr[N];
    int SP, ro;
    inline int re()
    {
        int x = 0;
        char c = getchar();
        bool p = 0;
        for (; c < '0' || c > '9'; c = getchar())
            p |= c == '-';
        for (; c >= '0' && c <= '9'; c = getchar())
            x = x * 10 + c - '0';
        return p ? -x : x;
    }
    inline int maxn(int x, int y){ return x > y ? x : y; }
    inline int minn(int x, int y){ return x < y ? x : y; }
    inline void pp(int x){ tr[x].si = tr[tr[x].so[0]].si + tr[tr[x].so[1]].si + tr[x].s; }
    inline int who(int x){ return tr[tr[x].fa].so[0] ^ x ? 1 : 0; }
    inline void ch(int x, int fa, int lr)
    {
    	tr[fa].so[lr] = x;
    	tr[x].fa = fa;
    }
    void rtt(int x)
    {
    	int y = tr[x].fa, r = tr[y].fa, soy = who(x), sor = who(y);
    	ch(tr[x].so[soy ^ 1], y, soy);
    	ch(y, x, soy ^ 1);
    	ch(x, r, sor);
    	pp(y);
    	pp(x);
    }
    void sy(int x, int y)
    {
    	int z;
    	if (!(ro ^ y))
    		ro = x;
    	y = tr[y].fa;
    	while (tr[x].fa ^ y)
    	{
    		z = tr[x].fa;
    		if (!(tr[z].fa ^ y))
    			rtt(x);
    		else
    		{
    			who(x) ^ who(z) ? rtt(x) : rtt(z);
    			rtt(x);
    		}
    	}
    }
    inline int newnode(int x, int fa)
    {
    	tr[++SP].fa = fa;
    	tr[SP].v = x;
    	tr[SP].si = tr[SP].s = 1;
    	return SP;
    }
    void is(int x)
    {
    	if (!ro)
    		ro = newnode(x, 0);
    	else
    		for (int y, k = ro; ; k = tr[k].so[y])
    		{
    			tr[k].si++;
    			if (!(tr[k].v ^ x))
    			{
    				tr[k].s++;
    				sy(k, ro);
    				return;
    			}
    			if (!tr[k].so[y = x < tr[k].v ? 0 : 1])
    			{
    				int nw = newnode(x, k);
    				tr[k].so[y] = nw;
    				sy(nw, ro);
    				return;
    			}
    		}
    }
    inline int fin(int x)
    {
    	for (int k = ro; k; k = tr[k].so[x < tr[k].v ? 0 : 1])
    		if (!(tr[k].v ^ x))
    		{
    			sy(k, ro);
    			return k;
    		}
    	return 0;
    }
    void dt(int x)
    {
    	int k = fin(x), y;
    	if (!k)
    		return;
    	if (tr[k].s > 1)
    	{
    		tr[k].s--;
    		tr[k].si--;
    		return;
    	}
    	if (!tr[k].so[0] && !tr[k].so[1])
    	{
    		ro = 0;
    		return;
    	}
    	if (!tr[k].so[0])
    	{
    		ro = tr[k].so[1];
    		tr[ro].fa = 0;
    		return;
    	}
    	if (!tr[k].so[1])
    	{
    		ro = tr[k].so[0];
    		tr[ro].fa = 0;
    		return;
    	}
    	for (y = tr[k].so[0]; tr[y].so[1]; y = tr[y].so[1]);
    	sy(y, tr[k].so[0]);
    	ch(tr[k].so[1], y, 1);
    	ro = y;
    	tr[y].fa = 0;
    	pp(y);
    }
    inline int qu_rk(int x){ return tr[tr[fin(x)].so[0]].si + 1; }
    int qu_nu(int x)
    {
    	for (int k = ro, nw; ; )
    	{
    		nw = tr[k].si - tr[tr[k].so[1]].si;
    		if (x > tr[tr[k].so[0]].si && x <= nw)
    		{
    			sy(k, ro);
    			return tr[k].v;
    		}
    		if (x < nw)
    			k = tr[k].so[0];
    		else
    		{
    			k = tr[k].so[1];
    			x -= nw;
    		}
    	}
    }
    inline int qu_pre(int x)
    {
    	int s = -1e9;
    	for (int k = ro; k; k = tr[k].so[x <= tr[k].v ? 0 : 1])
    		if (x > tr[k].v)
    			s = maxn(s, tr[k].v);
    	return s;
    }
    inline int qu_suc(int x)
    {
    	int s = 1e9;
    	for (int k = ro; k; k = tr[k].so[x >= tr[k].v ? 1 : 0])
    		if (x < tr[k].v)
    			s = minn(s, tr[k].v);
    	return s;
    }
    int main()
    {
    	int i, n, p;
    	n = re();
    	for (i = 1; i <= n; i++)
    	{
    		p = re();
    		if (!(p ^ 1))
    			is(re());
    		else
    			if (!(p ^ 2))
    				dt(re());
    			else
    				if (!(p ^ 3))
    					printf("%d
    ", qu_rk(re()));
    				else
    					if (!(p ^ 4))
    						printf("%d
    ", qu_nu(re()));
    					else
    						if (!(p ^ 5))
    							printf("%d
    ", qu_pre(re()));
    						else
    							printf("%d
    ", qu_suc(re()));
    	}
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    const int N = 1e5 + 10;
    const int M = N << 1;
    int fi[N], ne[M], di[M], val[N], si[N], fa[N], id[N], fid[N], son[N], top[N], S[M << 1], ad[M << 1], dep[N], l = 1, cnt, mod, n;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y) { di[++l] = y; ne[l] = fi[x]; fi[x] = l; }
    inline void sw(int &x, int &y) { int z = x; x = y; y = z; }
    void dfs_1(int x)
    {
    	int i, y;
    	si[x] = 1;
    	for (i = fi[x]; i; i = ne[i])
    		if ((y = di[i]) ^ fa[x])
    		{
    			fa[y] = x; dep[y] = dep[x] + 1;
    			dfs_1(y); si[x] += si[y];
    			if (si[y] > si[son[x]])
    				son[x] = y;
    		}
    }
    void dfs_2(int x, int tp)
    {
    	int i, y;
    	top[x] = tp; id[x] = ++cnt; fid[cnt] = x;
    	if (son[x])
    		dfs_2(son[x], tp);
    	for (i = fi[x]; i; i = ne[i])
    	{
    		y = di[i];
    		if (y ^ fa[x] && y ^ son[x])
    			dfs_2(y, y);
    	}
    }
    inline void pushup(int r) { S[r] = (1LL * S[r << 1] + S[r << 1 | 1]) % mod; }
    inline void pushdown(int r, int x, int y)
    {
    	int &k = ad[r];
    	if (k)
    	{
    		int lx = r << 1, ly = r << 1 | 1, mid = (x + y) >> 1;
    		ad[lx] = (1LL * ad[lx] + k) % mod; ad[ly] = (1LL * ad[ly] + k) % mod;
    		S[lx] = (1LL * k * (mid - x + 1) + S[lx]) % mod;
    		S[ly] = (1LL * k * (y - mid) + S[ly]) % mod;
    		k = 0;
    	}
    }
    void bu(int r, int x, int y)
    {
    	if (x ^ y)
    	{
    		int mid = (x + y) >> 1;
    		bu(r << 1, x, mid);
    		bu(r << 1 | 1, mid + 1, y);
    		pushup(r);
    	}
    	else
    		S[r] = val[fid[x]];
    }
    void modify(int r, int x, int y, int ql, int qr, int k)
    {
    	if (ql <= x && y <= qr)
    	{
    		ad[r] = (1LL * ad[r] + k) % mod;
    		S[r] = (1LL * k * (y - x + 1) + S[r]) % mod;
    		return;
    	}
    	int mid = (x + y) >> 1;
    	pushdown(r, x, y);
    	if (ql <= mid)
    		modify(r << 1, x, mid, ql, qr, k);
    	if (mid < qr)
    		modify(r << 1 | 1, mid + 1, y, ql, qr, k);
    	pushup(r);
    }
    int qu(int r, int x, int y, int ql, int qr)
    {
    	if (ql <= x && y <= qr)
    		return S[r];
    	int mid = (x + y) >> 1, s = 0;
    	pushdown(r, x, y);
    	if (ql <= mid)
    		s = (1LL * s + qu(r << 1, x, mid, ql, qr)) % mod;
    	if (mid < qr)
    		s = (1LL * s + qu(r << 1 | 1, mid + 1, y, ql, qr)) % mod;
    	return s;
    }
    void tr_modify(int x, int y, int z)
    {
    	for (; top[x] ^ top[y]; y = fa[top[y]])
    	{
    		if (dep[top[x]] > dep[top[y]])
    			sw(x, y);
    		modify(1, 1, n, id[top[y]], id[y], z);
    	}
    	if (id[x] > id[y])
    		sw(x, y);
    	modify(1, 1, n, id[x], id[y], z);
    }
    int tr_qu(int x, int y)
    {
    	int s = 0;
    	for (; top[x] ^ top[y]; y = fa[top[y]])
    	{
    		if (dep[top[x]] > dep[top[y]])
    			sw(x, y);
    		s = (1LL * s + qu(1, 1, n, id[top[y]], id[y])) % mod;
    	}
    	if (id[x] > id[y])
    		sw(x, y);
    	return s = (1LL * s + qu(1, 1, n, id[x], id[y])) % mod;
    }
    int main()
    {
    	int i, m, ro, p, x, y;
    	n = re(); m = re(); ro = re(); mod = re();
    	for (i = 1; i <= n; i++)
    		val[i] = re();
    	for (i = 1; i < n; i++)
    	{
    		x = re(); y = re();
    		add(x, y); add(y, x);
    	}
    	dep[ro] = 1; dfs_1(ro); dfs_2(ro, ro);
    	bu(1, 1, n);
    	for (i = 1; i <= m; i++)
    	{
    		p = re(); x = re();
    		if (p ^ 4)
    		{
    			y = re();
    			if (p ^ 1)
    				p ^ 3 ? (void)printf("%d
    ", tr_qu(x, y)) : modify(1, 1, n, id[x], id[x] + si[x] - 1, y);
    			else
    				tr_modify(x, y, re());
    		}
    		else
    			printf("%d
    ", qu(1, 1, n, id[x], id[x] + si[x] - 1));
    	}
    	return 0;
    }
    

    数位(DP)

    虽然是套路,但这个模板还是挺灵活的。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N = ...;
    ll f[N][...]...;//看题目定状态
    int a[N];
    inline ll re()
    {
    	ll x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    //有些题不需要考虑前导零,有些则需要
    ll dfs(int pos/*剩余枚举位数*/,.../*一些要记录的状态*/, int lm/*当前位是否有限制*/, int zero/*是否有前导零*/)
    {
    	if (pos < 0)//枚举结束,返回
    		return s;
    	...//有些题可能要剪枝
    	if (!lm && !zero && f[pos][s] > -1)//如果没有限制,返回记忆化的数据
    		return f[pos][...]...;
    	int i, k = lm ? a[pos] : 9;//判断枚举上界
    	ll S = 0;
    	for (i = 0; i <= k; i++)//枚举该位
    	{
    		if ()
    			...
    		else
    			if ()
    				...//根据题目的不同操作
    		S += dfs(pos - 1,.../*状态转移*/, lm && i == a[pos], zero && !i);//这里比较灵活,视题目而定
    	}
    	if (!lm && !zero)//没有限制则记忆化
    		return f[pos][...]... = S;
    	return S;
    }
    ll calc(ll x)//拆分数位
    {
    	int k = 0;
    	memset(f, -1, sizeof(f));//一般初始化为-1,有些题目只需初始化一次
    	while (x > 0)
    	{
    		a[k++] = x % 10;
    		x /= 10;
    	}
    	return dfs(k - 1,.../*初始状态*/, 1, 1);
    }
    int main()
    {
    	ll x, y;
    	x = re();
    	y = re();
    	printf("%d", calc(y) - calc(x - 1));//前缀和思想
    	return 0;
    }
    

    图论

    单源最短路径

    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int N = 1e5 + 10;
    const int M = 2e5 + 10;
    struct dd {
    	int x, D;
    	bool operator < (const dd &b) const { return D > b.D; }
    };
    int fi[N], di[M], ne[M], da[M], dis[N], l;
    bool v[N];
    priority_queue<dd>q;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y, int z)
    {
    	di[++l] = y;
    	da[l] = z;
    	ne[l] = fi[x];
    	fi[x] = l;
    }
    void dij(int st)
    {
    	int i, x, y;
    	memset(dis, 60, sizeof(dis));
    	dis[st] = 0;
    	q.push((dd){st, 0});
    	while (!q.empty())
    	{
    		x = q.top().x;
    		q.pop();
    		if (v[x])
    			continue;
    		v[x] = 1;
    		for (i = fi[x]; i; i = ne[i])
    			if (dis[y = di[i]] > dis[x] + da[i])
    				q.push((dd){y, dis[y] = dis[x] + da[i]});
    	}
    }
    int main()
    {
    	int i, x, y, n, m, z, st;
    	n = re();
    	m = re();
    	st = re();
    	for (i = 1; i <= m; i++)
    	{
    		x = re();
    		y = re();
    		z = re();
    		add(x, y, z);
    	}
    	dij(st);
    	for (i = 1; i <= n; i++)
    		printf("%d ", dis[i]);
    	return 0;
    }
    
    • SPFA
      模板传送门
      关于SPFA,他已经死了,让我们挂一张遗像
    #include<cstdio>
    using namespace std;
    const int N = 1e4 + 10;
    const int M = 5e5 + 10;
    const int L = 5e5;
    const int K = (1LL << 31) - 1;
    int fi[N], di[M], ne[M], da[M], dis[N], q[M], l;
    bool v[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y, int z)
    {
    	di[++l] = y;
    	da[l] = z;
    	ne[l] = fi[x];
    	fi[x] = l;
    }
    void spfa(int st)
    {
    	int i, x, y, head = 0, tail = 1;
    	q[1] = st;
    	dis[st] = 0;
    	while (head ^ tail)
    	{
    		if (!(++head ^ L))
    			head = 1;
    		x = q[head];
    		v[x] = 0;
    		for (i = fi[x]; i; i = ne[i])
    			if (dis[y = di[i]] > dis[x] + da[i])
    			{
    				dis[y] = dis[x] + da[i];
    				if (!v[y])
    				{
    					if (!(++tail ^ L))
    						tail = 1;
    					q[tail] = y;
    					v[y] = 1;
    				}
    			}
    	}
    }
    int main()
    {
    	int i, x, y, n, m, st, z;
    	n = re();
    	m = re();
    	st = re();
    	for (i = 1; i <= m; i++)
    	{
    		x = re();
    		y = re();
    		z = re();
    		add(x, y, z);
    	}
    	for (i = 1; i <= n; i++)
    		dis[i] = K;
    	spfa(st);
    	for (i = 1; i <= n; i++)
    		printf("%d ", dis[i]);
    	return 0;
    }
    

    多源最短路径

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 510;
    int a[N][N], b[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline int minn(int x, int y){ return x < y ? x : y; }
    int main()
    {
    	int i, j, k, n, m, l, x, y, mi = 1e9, mi_id;
    	n = re();
    	l = re();
    	m = re();
    	for (i = 1; i <= l; i++)
    		b[i] = re();
    	memset(a, 60, sizeof(a));
    	for (i = 1; i <= m; i++)
    	{
    		x = re();
    		y = re();
    		a[y][x] = a[x][y] = re();
    	}
    	for (i = 1; i <= n; i++)
    		a[i][i] = 0;
    	for (k = 1; k <= n; k++)
    		for (i = 1; i <= n; i++)
    			if (i ^ k)
    				for (j = 1; j < i; j++)
    					a[i][j] = a[j][i] = minn(a[i][j], a[i][k] + a[k][j]);
    	for (i = 1; i <= n; i++)
    	{
    		int s = 0;
    		for (j = 1; j <= l; j++)
    			s += a[i][b[j]];
    		if (s < mi)
    		{
    			mi = s;
    			mi_id = i;
    		}
    	}
    	printf("%d", mi_id);
    	return 0;
    }
    

    最小生成树

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 5010;
    const int M = 2e5 + 10;
    struct dd {
    	int x, y, z;
    };
    dd a[M];
    int fa[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    int fin(int x)
    {
    	if (!(fa[x] ^ x))
    		return x;
    	return fa[x] = fin(fa[x]);
    }
    bool comp(dd x, dd y){ return x.z < y.z; }
    int main()
    {
    	int i, n, m, x, y, s = 0, k = 0;
    	n = re();
    	m = re();
    	for (i = 1; i <= m; i++)
    	{
    		a[i].x = re();
    		a[i].y = re();
    		a[i].z = re();
    	}
    	sort(a + 1, a + m + 1, comp);
    	for (i = 1; i <= n; i++)
    		fa[i] = i;
    	for (i = 1; i <= m && k ^ (n - 1); i++)
    	{
    		x = fin(a[i].x);
    		y = fin(a[i].y);
    		if (x ^ y)
    		{
    			fa[x] = y;
    			s += a[i].z;
    			k++;
    		}
    	}
    	k ^ (n - 1) ? printf("orz") : printf("%d", s);
    	return 0;
    }
    
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 5e3 + 10;
    int a[N][N], dis[N], n;
    bool v[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline int minn(int x, int y) { return x < y ? x : y; }
    void prim()
    {
    	int i, j, x;
    	memset(dis, 60, sizeof(dis));
    	dis[1] = 0;
    	for (i = 1; i <= n; i++)
    	{
    		for (x = 0, j = 1; j <= n; j++)
    			if (!v[j] && (!x || dis[j] < dis[x]))
    				x = j;
    		v[x] = 1;
    		for (j = 1; j <= n; j++)
    			if (!v[j])
    				dis[j] = minn(dis[j], a[x][j]);
    	}
    }
    int main()
    {
    	int i, m, x, y, s = 0;
    	n = re(); m = re();
    	memset(a, 60, sizeof(a));
    	for (i = 1; i <= m; i++)
    	{
    		x = re(); y = re();
    		a[x][y] = a[y][x] = re();
    	}
    	prim();
    	for (i = 1; i <= n; i++)
    		s += dis[i];
    	return printf("%d", s), 0;
    }
    

    树的直径

    #include<cstdio>
    using namespace std;
    const int N = 1e5 + 10;
    int di[N << 1], ne[N << 1], da[N << 1], fi[N], d[N], l = 1, ans;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y, int z) { di[++l] = y; da[l] = z; ne[l] = fi[x]; fi[x] = l; }
    inline int maxn(int x, int y) { return x > y ? x : y; }
    void dp(int x, int fa)
    {
    	int i, y;
    	for (i = fi[x]; i; i = ne[i])
    		if ((y = di[i]) ^ fa)
    		{
    			dp(y, x);
    			ans = maxn(ans, d[x] + d[y] + da[i]);
    			d[x] = maxn(d[x], d[y] + da[i]);
    		}
    }
    int main()
    {
    	int i, n, m, x, y, z;
    	n = re(); m = re();
    	for (i = 1; i <= m; i++)
    	{
    		x = re(); y = re(); z = re();
    		add(x, y, z); add(y, x, z);
    	}
    	dp(1, 0);
    	return printf("%d", ans), 0;
    }
    
    • DFS
      模板传送门
      注意有负边权时,DFS并不能跑出正确的直径。

    #include<cstdio>
    using namespace std;
    const int N = 1e5 + 10;
    int fi[N], di[N << 1], ne[N << 1], da[N << 1], ans, poi, l = 1;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y, int z) { di[++l] = y; da[l] = z; ne[l] = fi[x]; fi[x] = l; }
    void dfs(int x, int fa, int d)
    {
    	int i, y;
    	if (ans < d)
    		ans = d, poi = x;
    	for (i = fi[x]; i; i = ne[i])
    		if ((y = di[i]) ^ fa)
    			dfs(y, x, d + da[i]);
    }
    int main()
    {
    	int i, n, m, x, y, z;
    	n = re(); m = re();
    	for (i = 1; i <= m; i++)
    	{
    		x = re(); y = re(); z = re();
    		add(x, y, z); add(y, x, z);
    	}
    	dfs(1, 0, 0); ans = 0; dfs(poi, 0, 0);
    	return printf("%d", ans), 0;
    }
    

    (LCA)

    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int N = 5e5 + 10;
    const int M = 20;
    int fi[N], di[N << 1], ne[N << 1], f[N][M], dep[N], l = 1, gn;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y) { di[++l] = y; ne[l] = fi[x]; fi[x] = l; }
    inline void sw(int &x, int &y) { int z = x; x = y; y = z; }
    void dfs(int x, int fa)
    {
    	int i, y;
    	for (i = 1; i <= gn; i++)
    		f[x][i] = f[f[x][i - 1]][i - 1];
    	for (i = fi[x]; i; i = ne[i])
    		if ((y = di[i]) ^ fa)
    		{
    			f[y][0] = x;
    			dep[y] = dep[x] + 1;
    			dfs(y, x);
    		}
    }
    inline int lca(int x, int y)
    {
    	int i;
    	if (dep[x] > dep[y])
    		sw(x, y);
    	for (i = gn; ~i; i--)
    		if (dep[f[y][i]] >= dep[x])
    			y = f[y][i];
    	if (!(x ^ y)) return x;
    	for (i = gn; ~i; i--)
    		if (f[x][i] ^ f[y][i])
    			x = f[x][i], y = f[y][i];
    	return f[x][0];
    }
    int main()
    {
    	int i, n, m, ro, x, y;
    	n = re(); m = re(); ro = re();
    	for (i = 1; i < n; i++)
    	{
    		x = re(); y = re();
    		add(x, y); add(y, x);
    	}
    	gn = log(n) / log(2); dep[ro] = 1; dfs(ro, 0);
    	for (i = 1; i <= m; i++)
    	{
    		x = re(); y = re();
    		printf("%d
    ", lca(x, y));
    	}
    	return 0;
    }
    
    #include<cstdio>
    using namespace std;
    const int N = 5e5 + 10;
    const int M = N << 1;
    int fi[N], ne[M], di[M], ans[N], qu_fi[N], qu_di[M], qu_ne[M], fa[N], id[M], v[N], l = 1, qu_l = 1;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y) { di[++l] = y; ne[l] = fi[x]; fi[x] = l; }
    inline void qu_add(int x, int y, int z) { qu_di[++qu_l] = y; id[qu_l] = z; qu_ne[qu_l] = qu_fi[x]; qu_fi[x] = qu_l; }
    int fin(int x)
    {
    	if (!(x ^ fa[x]))
    		return x;
    	return fa[x] = fin(fa[x]);
    }
    void tarjan(int x)
    {
    	int i, y;
    	v[x] = 1;
    	for (i = fi[x]; i; i = ne[i])
    		if (!v[y = di[i]])
    			tarjan(y), fa[y] = x;
    	for (i = qu_fi[x]; i; i = qu_ne[i])
    		if (!(v[y = qu_di[i]] ^ 2))
    			ans[id[i]] = fin(y);
    	v[x] = 2;
    }
    int main()
    {
    	int i, n, m, x, y, ro;
    	n = re(); m = re(); ro = re();
    	for (i = 1, fa[n] = n; i < n; i++)
    	{
    		x = re(); y = re(); fa[i] = i;
    		add(x, y); add(y, x);
    	}
    	for (i = 1; i <= m; i++)
    	{
    		x = re(); y = re();
    		qu_add(x, y, i); qu_add(y, x, i);
    	}
    	tarjan(ro);
    	for (i = 1; i <= m; i++)
    		printf("%d
    ", ans[i]);
    	return 0;
    }
    

    (Tarjan)算法

    • 边双连通分量(割边/桥)
      并没有找到什么好的模板。就随便打了个。
    #include<cstdio>
    using namespace std;
    const int N = 2e4 + 10;
    const int M = 1e5 + 10;
    int fi[N], di[M], ne[M], bl[N], dfn[N], low[N], l = 1, DCC, ti;
    bool br[M];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y)
    {
    	di[++l] = y;
    	ne[l] = fi[x];
    	fi[x] = l;
    }
    inline int minn(int x, int y){ return x < y ? x : y; }
    void tarjan(int x, int la)
    {
    	int i, y;
    	dfn[x] = low[x] = ++ti;
    	for (i = fi[x]; i; i = ne[i])
    		if (!dfn[y = di[i]])
    		{
    			tarjan(y, i);
    			low[x] = minn(low[x], low[y]);
    			if (low[y] > dfn[x])
    				br[i] = br[i ^ 1] = 1;
    		}
    		else
    			if (i ^ la ^ 1)
    				low[x] = minn(low[x], dfn[y]);
    }
    void dfs(int x)
    {
    	int i, y;
    	bl[x] = DCC;
    	for (i = fi[x]; i; i = ne[i])
    		if (!bl[y = di[i]] && !br[i])
    			dfs(y);
    }
    int main()
    {
    	int i, n, m, x, y;
    	n = re();
    	m = re();
    	for (i = 1; i <= m; i++)
    	{
    		x = re();
    		y = re();
    		add(x, y);
    		add(y, x);
    	}
    	for (i = 1; i <= n; i++)
    		if (!dfn[i])
    			tarjan(i, 0);
    	for (i = 1; i <= n; i++)
    		if (!bl[i])
    		{
    			++DCC;
    			dfs(i);
    		}
    	printf("%d", DCC);
    	return 0;
    }
    
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 1e4 + 10;
    const int M = 1e5 + 10;
    struct eg {
    	int x, y;
    };
    eg a[M];
    int fi[N], ne[M], di[M], cfi[N], cne[M], cdi[M], val[N], Sval[N], bl[N], sta[N], dfn[N], low[N], dis[N], q[M], ru[N], l = 1, cl = 1, SCC, ti, top;
    bool v[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y) { di[++l] = y; ne[l] = fi[x]; fi[x] = l; }
    inline void cadd(int x, int y) { cdi[++cl] = y; cne[cl] = cfi[x]; cfi[x] = cl; ru[y]++; }
    inline int maxn(int x, int y) { return x > y ? x : y; }
    inline int minn(int x, int y) { return x < y ? x : y; }
    void tarjan(int x)
    {
    	int i, y;
    	dfn[x] = low[x] = ++ti;
    	sta[++top] = x; v[x] = 1;
    	for (i = fi[x]; i; i = ne[i])
    		if (!dfn[y = di[i]])
    		{
    			tarjan(y);
    			low[x] = minn(low[x], low[y]);
    		}
    		else
    			if (v[y])
    				low[x] = minn(low[x], dfn[y]);
    	if (!(low[x] ^ dfn[x]))
    	{
    		SCC++;
    		do
    		{
    			y = sta[top--];
    			Sval[SCC] += val[y];
    			bl[y] = SCC; v[y] = 0;
    		} while (x ^ y);
    	}
    }
    int topsort()
    {
    	int i, x, y, ma = 0, head = 0, tail = 0;
    	memset(dis, 195, sizeof(dis));
    	for (i = 1; i <= SCC; i++)
    		if (!ru[i])
    			dis[i] = Sval[i], q[++tail] = i;
    	while (head ^ tail)
    	{
    		x = q[++head];
    		ma = maxn(ma, dis[x]);
    		for (i = cfi[x]; i; i = cne[i])
    		{
    			y = cdi[i];
    			dis[y] = maxn(dis[y], dis[x] + Sval[y]);
    			if (!(--ru[y]))
    				q[++tail] = y;
    		}
    	}
    	return ma;
    }
    int main()
    {
    	int i, n, m;
    	n = re(); m = re();
    	for (i = 1; i <= n; i++)
    		val[i] = re();
    	for (i = 1; i <= m; i++)
    	{
    		a[i].x = re(); a[i].y = re();
    		add(a[i].x, a[i].y);
    	}
    	for (i = 1; i <= n; i++)
    		if (!dfn[i])
    			tarjan(i);
    	for (i = 1; i <= m; i++)
    		if (bl[a[i].x] ^ bl[a[i].y])
    			cadd(bl[a[i].x], bl[a[i].y]);
    	return printf("%d", topsort()), 0;
    }
    //附裸的找割点
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 2e4 + 10;
    const int M = 2e5 + 10;
    int fi[N], ne[M], di[M], dfn[N], low[N], cut_poi[N], l = 1, ti, ro, poi_s;
    bool v[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y) { di[++l] = y; ne[l] = fi[x]; fi[x] = l; }
    inline int minn(int x, int y) { return x < y ? x : y; }
    void tarjan(int x)
    {
    	int i, y, k = 0;
    	dfn[x] = low[x] = ++ti;
    	for (i = fi[x]; i; i = ne[i])
    		if (!dfn[y = di[i]])
    		{
    			tarjan(y);
    			low[x] = minn(low[x], low[y]);
    			if (low[y] >= dfn[x])
    				if (!v[x] && (x ^ ro || (++k) > 1))
    					cut_poi[++poi_s] = x, v[x] = 1;
    		}
    		else
    			low[x] = minn(low[x], dfn[y]);
    }
    int main()
    {
    	int i, n, m, x, y;
    	n = re(); m = re();
    	for (i = 1; i <= m; i++)
    	{
    		x = re(); y = re();
    		add(x, y); add(y, x);
    	}
    	for (i = 1; i <= n; i++)
    		if (!dfn[i])
    			ro = i, tarjan(i);
    	sort(cut_poi + 1, cut_poi + poi_s + 1);
    	printf("%d
    ", poi_s);
    	for (i = 1; i <= poi_s; i++)
    		printf("%d ", cut_poi[i]);
    	return 0;
    }
    

    二分图匹配

    • 匈牙利算法
      模板传送门
      二分图最大匹配模板。
      简单记下二分图其它的内容。
      二分图最小点覆盖,求最小的点集使得图中任意一条边都至少有一个端点属于这个点集,其值等于最大匹配数
      二分图最大独立集,求最大的点集使得任意两个点集中的点都没有一条边相连,其值等于二分图点数减去最大匹配数
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 2e3 + 10;
    const int M = 1e6 + 10;
    int fi[N], ne[M], di[M], match[N], l = 1;
    bool v[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y) { di[++l] = y; ne[l] = fi[x]; fi[x] = l; }
    bool dfs(int x)
    {
    	int i, y;
    	for (i = fi[x]; i; i = ne[i])
    		if (!v[y = di[i]])
    		{
    			v[y] = 1;
    			if (!match[y] || dfs(match[y]))
    			{
    				match[y] = x;
    				return true;
    			}
    		}
    	return false;
    }
    int main()
    {
    	int i, n, m, e, x, y, s = 0;
    	n = re(); m = re(); e = re();
    	for (i = 1; i <= e; i++)
    	{
    		x = re(); y = re();
    		if (x > n || y > m) continue;
    		add(x, y + n);
    	}
    	for (i = 1; i <= n; i++)
    	{
    		memset(v, 0, sizeof(v));
    		if (dfs(i))
    			s++;	
    	}
    	return printf("%d", s), 0;
    }
    

    网络流

    (虽然感觉这玩意并没有什么用)

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 1e4 + 10;
    const int M = 2e5 + 10;
    int fi[N], di[M], ne[M], da[M], de[N], cu[N], q[M], st, ed, l = 1;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y, int z)
    {
    	di[++l] = y;
    	da[l] = z;
    	ne[l] = fi[x];
    	fi[x] = l;
    }
    inline int minn(int x, int y){ return x < y ? x : y; }
    bool bfs()
    {
    	memset(de, 0, sizeof(de));
    	int i, x, y, head = 0, tail = 1;
    	q[1] = st;
    	de[st] = 1;
    	while (head ^ tail)
    	{
    		x = q[++head];
    		for (i = fi[x]; i; i = ne[i])
    			if (!de[y = di[i]] && da[i] > 0)
    			{
    				de[y] = de[x] + 1;
    				if (!(y ^ ed))
    					return true;
    				q[++tail] = y;
    			}
    	}
    	return false;
    }
    int dfs(int x, int k)
    {
    	if (!(x ^ ed))
    		return k;
    	int y, mi;
    	for (int &i = cu[x]; i; i = ne[i])
    		if (!(de[y = di[i]] ^ (de[x] + 1)) && da[i] > 0)
    		{
    			mi = dfs(y, minn(k, da[i]));
    			if (mi > 0)
    			{
    				da[i] -= mi;
    				da[i ^ 1] += mi;
    				return mi;
    			}
    		}
    	return 0;
    }
    int main()
    {
    	int i, n, m, x, y, z, s = 0;
    	n = re();
    	m = re();
    	st = re();
    	ed = re();
    	for (i = 1; i <= m; i++)
    	{
    		x = re();
    		y = re();
    		z = re();
    		add(x, y, z);
    		add(y, x, 0);
    	}
    	while (bfs())
    	{
    		for (i = 1; i <= n; i++)
    			cu[i] = fi[i];
    		for (; (x = dfs(st, 1e9)) > 0; s += x);
    	}
    	printf("%d", s);
    	return 0;
    }
    
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 5010;
    const int M = 1e5 + 10;
    int fi[N], di[M], ne[M], da[M], co[M], q[M], flo[N], pre[N], dis[N], l = 1, st, ed;
    bool v[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
        bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
        for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
        return p ? -x : x;
    }
    inline void add(int x, int y, int z, int c) { di[++l] = y; da[l] = z; co[l] = c; ne[l] = fi[x]; fi[x] = l; }
    inline int minn(int x, int y) { return x < y ? x : y; }
    bool spfa()
    {
        int i, x, y, head = 0, tail = 1;
        memset(dis, 60, sizeof(dis));
        dis[st] = 0; q[1] = st; flo[st] = 1e9;
        while (head ^ tail)
        {
    		x = q[++head]; v[x] = 0;
    		for (i = fi[x]; i; i = ne[i])
    			if (dis[y = di[i]] > dis[x] + co[i] && da[i] > 0)
    			{
    				dis[y] = dis[x] + co[i];
    				pre[y] = i; flo[y] = minn(flo[x], da[i]);
    				if (!v[y])
    					q[++tail] = y, v[y] = 1;
    			}
        }
        return dis[ed] < 1e9;
    }
    int main()
    {
        int i, n, m, x, y, z, c, s = 0, f = 0;
        n = re(); m = re(); st = re(); ed = re();
        for (i = 1; i <= m; i++)
        {
    		x = re(); y = re(); z = re(); c = re();
    		add(x, y, z, c); add(y, x, 0, -c);
        }
        while (spfa())
        {
    		s += flo[ed] * dis[ed]; f += flo[ed];
    		for (x = ed; x ^ st; x = di[i ^ 1])
            	i = pre[x], da[i] -= flo[ed], da[i ^ 1] += flo[ed];
        }
        printf("%d %d", f, s);
        return 0;
    }
    
  • 相关阅读:
    单链表的学习
    数据库连接
    Oracle学习指南
    Java登录第一版
    LeetCode(141): Linked List Cycle
    LeetCode(24): Swap Nodes in Pairs
    LeetCode(2):Add Two Numbers
    LeetCode(83):Remove Duplicates from Sorted List
    LeetCode(21):Merge Two Sorted Lists
    LeetCode(234):Palindrome Linked List
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9910813.html
Copyright © 2011-2022 走看看