zoukankan      html  css  js  c++  java
  • CSP考前复习

    CSP考前复习

    前言

    因为loceaner太菜了,他什么东西都不会
    所以他打算学一个东西就记录一下
    不过因为他很菜,所以他不会写原理……
    而且,他希望在2019CSP之前不会断更
    就酱紫,就是写给他自己的……因为他太菜了

    基础算法

    小技巧

    [sum_{i = 0}^{x}C(x, i)* C(y, i) = C(x + y, x) ]

    使用负数下标

    如何使用负数下标呢?
    让数组前面有东西

    int y[100];
    int *z = y + 50;
    

    这样的话调用(z[-50])就变成了调用(y[0])

    z[-50] = y[0];
    

    然后这样就可以实现调用啦~

    其实还有一个更暴力的方法:用(map)

    (map)(log n)(map)
    (unordered\_map)(O(1))(map)(到(c++11)才会有)

    二维前缀和

    //知识点:二维前缀和
    /*
    By:Loceaner
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    const int N = 1000;
    
    int n, m;
    int a[N][N], b[N][N];
    
    int main() {
    	n = read(), m = read();
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			a[i][j] = read();
    			b[i][j] = a[i][j] + b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
    		}
    	}
    	for(int i, u1, v1, u2, v2; i <= m; i++) {
    		u1 = read(), v1 = read(), u2 = read(), v2 = read();
    		cout << b[u2][v2] - b[u1 - 1][v2] - b[u2][v1 - 1] + b[u1 - 1][v1 - 1] << '
    ';
    	} 
    	return 0;
    }
    
    

    三分法

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    const double eps = 1e-6;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n;
    double l, r, a[A];
    
    
    double f(double x) {
    	double ans = 0;
    	for(int i = 1; i <= n + 1; i++) ans = ans * x + a[i];
    	return ans;
    }
    
    int main() {
    	n = read(); scanf("%lf%lf", &l, &r);
    	for(int i = 1; i <= n + 1; i++) scanf("%lf", &a[i]);
    	while(r - l >= eps) {
    		double qwq = (r - l) / 3.0, lmid = l + qwq, rmid = r - qwq;
    		if(f(lmid) > f(rmid)) r = rmid; 
    		else l = lmid;
    	}
    	printf("%.5lf", l);
    	return 0;
    }
    

    二维差分

    //知识点:
    /*
    By:Loceaner
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    const int N = 1e3 + 11;
    
    int n, m, a[N][N];
    
    int main() {
    	n = read(), m = read();
    	for(int i = 1, u1, u2, v1, v2; i <= m; i++) {
    		u1 = read(), v1 = read(), u2 = read(), v2 = read();
    		a[u1][v1] += 1;
    		a[u2 + 1][v2 + 1] += 1;
    		a[u2 + 1][v1] -= 1;
    		a[u1][v2 + 1] -= 1;
    	}
    	//C[x1][y1] += x ,  C[x2 + 1][y2 + 1] += x ,  C[x1][y2 + 1] -= x , C[x2 + 1][y1] -= x;
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			a[i][j] = a[i][j] + a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];;
    		} 
    	}
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			cout << a[i][j] << ' ';
    		}
    		cout << '
    ';
    	}
    	return 0;
    }
    
    

    归并排序

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    int n, m, a[A], b[A];
    
    void solve(int l, int r) {
    	if(l == r) return;
    	int mid = (l + r) >> 1;
    	solve(l, mid), solve(mid + 1, r);
    	int i = l, j = mid + 1, k = l;
    	while(i <= mid && j <= r) {
    		if(a[i] <= a[j]) b[k++] = a[i++];
    		else b[k++] = a[j++];
    	}
    	while(i <= mid) b[k++] = a[i++]; 
    	while(j <= r) b[k++] = a[j++];
    	for(int i = l; i <= r; i++) a[i] = b[i];
    }
    
    int main() {
    //	freopen("a.in", "r", stdin);
    	n = read();
    	for(int i = 1; i <= n; i++) a[i] = read();
    	solve(1, n);
    	for(int i = 1; i <= n; i++) cout << a[i] << ' ';
    	return 0;
    }
    
    

    排序不等式

    给定3组数(a, b, c)
    (a[1])~(a[n]),(b[1])~(b[n]),(c[1])~(c[n])
    其中(c[1])~(c[n])(b[1])~(b[n])的乱序排列
    (a[1]*b[n]+a[2]*b[n-1]+...<=a[1]*c[1]+a[2]*c[2]+...<=a[1]*b[1]+a[2]*b[2]+...)
    即:逆序和 <= 乱序和 <= 正序和

    关于(long long)

    在日常的题目中,一定要看好数据范围,如果会爆(int)的话,不要忘记开(long long)(无数次被坑!!)

    高精度模板

    最让人烦的就是高精度了,某些题并不难,但是要写高精。。烦(color{white}{(ps:板子来自lfd)})

    namespace BigInteger {
    	struct Big_integer {
    		int d[10005], len;
    		void clean() {while(len > 1 and !d[len - 1]) len--;}
    		Big_integer() {memset(d, 0, sizeof d);len = 1;}
    		Big_integer(int num) {*this = num;}
    		Big_integer operator = (const char* num) {
    			memset(d, 0, sizeof d);
    			len = strlen(num);
    			for (int i = 0; i < len; i++) d[i] = num[len - 1 - i] - '0';
    			clean();
    			return *this;
    		}
    		Big_integer operator = (int num) {
    			char s[10005];
    			sprintf(s, "%d", num);
    			*this = s;
    			return *this;
    		}
    		Big_integer operator * (const Big_integer &b) const {
    			int i, j;
    			Big_integer c;
    			c.len = len + b.len;
    			for (j = 0; j < b.len; j++)
    				for (i = 0; i < len; i++)
    					c.d[i + j] += d[i] * b.d[j];
    			for (i = 0; i < c.len - 1; i++) c.d[i + 1] += c.d[i] / 10, c.d[i] %= 10;
    			c.clean();
    			return c;
    		}
    		Big_integer operator / (const int &b) {
    			int i, j, a = 0;
    			Big_integer c = *this;
    			for (i = len - 1; i >= 0; i--) {
    				a = a * 10 + d[i];
    				for (j = 0; j < 10; j++) if (a < b * (j + 1)) break;
    				c.d[i] = j;
    				a = a - b * j;
    			}
    			c.clean();
    			return c;
    		}
    		bool operator < (const Big_integer &b) const {
    			if (len != b.len) return len < b.len;
    			for (int i = len - 1; i >= 0; i--)
    				if (d[i] != b.d[i])
    					return d[i] < b.d[i];
    			return false;
    		}
    		string str() const {
    			char s[10005];
    			for (int i = 0; i < len; i++) s[len - 1 - i] = d[i] + '0';
    			return s;
    		}
    	};
    	istream& operator >> (istream& in, Big_integer &x) {
    		string s;
    		in >> s;
    		x = s.c_str();
    		return in;
    	}
    	ostream& operator << (ostream& out, const Big_integer &x) {
    		out << x.str();
    		return out;
    	}
    }
    using namespace BigInteger;
    

    数据结构

    树状数组

    单点修改,区间查询

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define lowbit(x) (x & (-x))
    using namespace std;
    
    const int A = 5e5 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, c[B];
    
    void update(int x, int k) {
    	while(x <= n) {
    		c[x] += k;
    		x += lowbit(x);
    	}
    }
    
    int query(int x) {
    	int ans = 0;
    	while(x) {
    		ans += c[x];
    		x -= lowbit(x);
    	}
    	return ans;
    }
    
    int main() {
    	n = read(), m = read();
    	for(int i = 1, a; i <= n; i++) {
    		a = read();
    		update(i, a);
    	}
    	while(m--) {
    		int opt = read(), x = read(), y = read();
    		if(opt == 1) update(x, y);
    		else cout << query(y) - query(x - 1) << '
    ';
    	}
    	return 0;
    }
    

    区间修改,单点查询

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define lowbit(x) (x & (-x))
    using namespace std;
    
    const int A = 5e5 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, c[B], a[B];
    
    void update(int x, int k) {
    	while(x <= n) {
    		c[x] += k;
    		x += lowbit(x);
    	}
    }
    
    int query(int x) {
    	int ans = 0;
    	while(x) {
    		ans += c[x];
    		x -= lowbit(x);
    	}
    	return ans;
    }
    
    int main() {
    	n = read(), m = read();
    	for(int i = 1; i <= n; i++) a[i] = read();
    	while(m--) {
    		int opt = read(), x = read(), y, k;
    		if(opt == 1) y = read(), k = read(), update(x, k), update(y + 1, -k);
    		else cout << a[x] + query(x) << '
    ';
    	}
    	return 0;
    }
    

    线段树

    区间修改,区间查询

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define int long long
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m;
    
    namespace Seg {
    	#define lson rt << 1
    	#define rson rt << 1 | 1
    	struct tree {
    		int l, r, w, lazy;
    	} t[A << 2];
    	inline void pushup(int rt) { t[rt].w = t[lson].w + t[rson].w; }
    	inline void pushdown(int rt) {
    		t[lson].lazy += t[rt].lazy, t[rson].lazy += t[rt].lazy;
    		t[lson].w += (t[lson].r - t[lson].l + 1) * t[rt].lazy;
    		t[rson].w += (t[rson].r - t[rson].l + 1) * t[rt].lazy;
    		t[rt].lazy = 0;
    	}
    	void build(int rt, int l, int r) {
    		t[rt].l = l, t[rt].r = r;
    		if(l == r) { t[rt].w = read(); return; }
    		int mid = (l + r) >> 1;
    		build(lson, l, mid), build(rson, mid + 1, r);
    		pushup(rt); return;
    	}
    	void update(int rt, int l, int r, int val) {
    		if(l <= t[rt].l && t[rt].r <= r) {
    			t[rt].lazy += val;
    			t[rt].w += (t[rt].r - t[rt].l + 1) * val;
    			return;
    		}
    		if(t[rt].lazy) pushdown(rt); 
    		int mid = (t[rt].l + t[rt].r) >> 1;
    		if(l <= mid) update(lson, l, r, val);
    		if(r > mid) update(rson, l, r, val);
    		pushup(rt); return;
    	}
    	int query(int rt, int l, int r) {
    		if(l <= t[rt].l && t[rt].r <= r) { return t[rt].w; }
    		if(t[rt].lazy) pushdown(rt); 
    		int mid = (t[rt].l + t[rt].r) >> 1, ans = 0;
    		if(l <= mid) ans += query(lson, l, r);
    		if(r > mid) ans += query(rson, l, r);
    		return ans;
    	}
    }
    
    signed main() {
    	n = read(), m = read();
    	Seg::build(1, 1, n);
    	while(m--) {
    		int opt = read(), x = read(), y = read(), k;
    		if(opt == 1) k = read(), Seg::update(1, x, y, k);
    		else cout << Seg::query(1, x, y) << '
    ';
    	}
    	return 0;
    }
    

    区间加,区间乘,区间求和

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define int long long
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, mod;
    
    namespace Seg {
    	#define lson rt << 1
    	#define rson rt << 1 | 1
    	struct tre {
    		int l, r, w, lazy1, lazy2;
    	} t[A << 2];
    	inline void pushup(int rt) {
    		t[rt].w = (t[lson].w + t[rson].w) % mod;
    	}
    	inline void tag1(int rt, int val) {
    		t[rt].lazy1 *= val, t[rt].lazy2 *= val;
    		t[rt].lazy1 %= mod, t[rt].lazy2 %= mod;		
    		t[rt].w *= val, t[rt].w %= mod;
    	}
    	inline void tag2(int rt, int val) {
    		t[rt].lazy2 += val; t[rt].lazy2 %= mod;
    		t[rt].w += (t[rt].r - t[rt].l + 1) * val, t[rt].w %= mod;
    	}
    	inline void pushdown(int rt) {
    		if(t[rt].lazy1 != 1) {
    			tag1(lson, t[rt].lazy1);
    			tag1(rson, t[rt].lazy1);
    			t[rt].lazy1 = 1;
    		}
    		if(t[rt].lazy2) {
    			tag2(lson, t[rt].lazy2);
    			tag2(rson, t[rt].lazy2);
    			t[rt].lazy2 = 0;
    		}
    	}
    	inline void build(int rt, int l, int r) {
    		t[rt].l = l, t[rt].r = r, t[rt].lazy1 = 1, t[rt].lazy2 = 0;
    		if(l == r) { t[rt].w = read(); return; }
    		int mid = (l + r) >> 1;
    		build(lson, l, mid), build(rson, mid + 1, r);
    		pushup(rt); return;
    	}
    	inline void mul(int rt, int l, int r, int val) {
    		if(l <= t[rt].l && t[rt].r <= r) return tag1(rt, val);
    		pushdown(rt);
    		int mid = (t[rt].l + t[rt].r) >> 1;
    		if(l <= mid) mul(lson, l, r, val);
    		if(r > mid) mul(rson, l, r, val);
    		pushup(rt); return;
    	}
    	inline void update(int rt, int l, int r, int val) {
    		if(l <= t[rt].l && t[rt].r <= r) return tag2(rt, val);
    		pushdown(rt);
    		int mid = (t[rt].l + t[rt].r) >> 1;
    		if(l <= mid) update(lson, l, r, val);
    		if(r > mid) update(rson, l, r, val);
    		pushup(rt); return;
    	}
    	inline int query(int rt, int l, int r) {
    		if(l <= t[rt].l && t[rt].r <= r) { return t[rt].w % mod; }
    		pushdown(rt);
    		int mid = (t[rt].l + t[rt].r) >> 1, ans = 0;
    		if(l <= mid) ans += query(lson, l, r), ans %= mod;
    		if(r > mid) ans += query(rson, l, r), ans %= mod;
    		return ans % mod;
    	}
    }
    
    signed main() {
    	n = read(), m = read(), mod = read();
    	Seg::build(1, 1, n);
    	while(m--) {
    		int opt = read(), x = read(), y = read(), k;
    		if(opt == 1) k = read() % mod, Seg::mul(1, x, y, k);
    		else if(opt == 2) k = read() % mod, Seg::update(1, x, y, k);
    		else cout << Seg::query(1, x, y) % mod << '
    ';
    	}
    	return 0;
    }
    

    单调栈

    for(int i = 0; i < T.size(); i++){
      while(! stk.empty() && stk.top() > T[i]){
        ​stk.pop();
      }
      stk.push(A[i]);
    }
    

    单调队列

    上经典的滑动窗口问题

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #define maxn 1000100
    using namespace std;
    int q[maxn], a[maxn];
    int n, k;
    void getmin() {
    	int head = 0, tail = 0;
    	for (int i = 1; i < k; i++) {
    		while (head <= tail && a[q[tail]] >= a[i]) tail--;
    		q[++tail] = i;
    	}
    	for (int i = k; i <= n; i++) {
    		while (head <= tail && a[q[tail]] >= a[i]) tail--;
    		q[++tail] = i;
    		while (q[head] <= i - k) head++;
    		printf("%d ", a[q[head]]);
    	}
    }
    
    void getmax() {
    	int head = 0, tail = 0;
    	for (int i = 1; i < k; i++) {
    		while (head <= tail && a[q[tail]] <= a[i]) tail--;
    		q[++tail] = i;
    	}
    	for (int i = k; i <= n; i++) {
    		while (head <= tail && a[q[tail]] <= a[i]) tail--;
    		q[++tail] = i;
    		while (q[head] <= i - k) head++;
    		printf("%d ", a[q[head]]);
    	}
    }
    
    int main() {
    	scanf("%d%d", &n, &k);
    	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    	getmin();
    	printf("
    ");
    	getmax();
    	printf("
    ");
    	return 0;
    }
    

    树剖

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e6 + 11;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    int n, m, root, mod, w[A], pre[A];
    
    struct node {
    	int to, nxt;
    } e[A];
    
    int head[A], cnt;
    
    inline void add_edge(int from, int to) {	
    	e[++cnt].to = to;
    	e[cnt].nxt = head[from];
    	head[from] = cnt;
    }
    
    namespace Seg {
    	struct tree {
    		int l, r, w, lazy;
    	} t[A]; 
    	#define lson rt << 1
    	#define rson rt << 1 | 1
    	inline void pushup(int rt) {
    		t[rt].w = (t[lson].w + t[rson].w) % mod;
    	}
    	inline void pushdown(int rt) {
    		t[lson].lazy += t[rt].lazy, t[rson].lazy += t[rt].lazy; 
    		t[lson].lazy %= mod, t[rson].lazy %= mod;
    		t[lson].w += (t[lson].r - t[lson].l + 1) * t[rt].lazy; t[lson].w %= mod;
    		t[rson].w += (t[rson].r - t[rson].l + 1) * t[rt].lazy; t[lson].w %= mod;
    		t[rt].lazy = 0;
    	}
    	void build(int rt, int l, int r) {
    		t[rt].l = l, t[rt].r = r;
    		if(l == r) { t[rt].w = w[pre[l]] % mod; return; }
    		int mid = (l + r) >> 1;
    		build(lson, l, mid); build(rson, mid + 1, r);
    		pushup(rt); return;
    	}
    	void add(int rt, int l, int r, int val) {
    		if(l <= t[rt].l && t[rt].r <= r) {
    			t[rt].lazy = (t[rt].lazy + val) % mod;
    			t[rt].w = (t[rt].w + (t[rt].r - t[rt].l + 1) * val) % mod;
    			return;
    		}
    		if(t[rt].lazy) pushdown(rt);
    		int mid = (t[rt].l + t[rt].r) >> 1;
    		if(l <= mid) add(lson, l, r, val); 
    		if(r > mid) add(rson, l, r, val);
    		pushup(rt);
    	}
    	int asksum(int rt, int l, int r) {
    		if(l <= t[rt].l && t[rt].r <= r) {
    			return t[rt].w % mod;
    		}
    		if(t[rt].lazy) pushdown(rt);
    		int mid = (t[rt].l + t[rt].r) >> 1, ans = 0;
    		if(l <= mid) ans += asksum(lson, l, r);
    		if(r > mid) ans += asksum(rson, l, r);
    		return ans;
    	}
    }
    
    int dfn[A], son[A], siz[A], dep[A], fa[A], top[A], tot;
    
    void dfs1(int now, int fr) {
    	siz[now] = 1, fa[now] = fr, dep[now] = dep[fr] + 1;
    	for(int i = head[now]; i; i = e[i].nxt) {
    		int to = e[i].to;
    		if(to == fr) continue; 
    		dfs1(to, now);
    		siz[now] += siz[to];
    		if(siz[to] > siz[son[now]]) son[now] = to;
    	}
    }
    
    void dfs2(int now, int tp) {
    	dfn[now] = ++tot, pre[tot] = now, top[now] = tp; 
    	if(son[now]) dfs2(son[now], tp);
    	for(int i = head[now]; i; i = e[i].nxt) {
    		int to = e[i].to;
    		if(to == fa[now] || to == son[now]) continue;
    		dfs2(to, to);
    	}
    }
    
    inline void add_qwq(int x, int y, int val) {
    	while(top[x] != top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		Seg::add(1, dfn[top[x]], dfn[x], val);
    		x = fa[top[x]];
    	}
    	if(dep[x] > dep[y]) swap(x, y);
    	Seg::add(1, dfn[x], dfn[y], val);
    	return;
    }
    
    inline int asksum_qwq(int x, int y) {
    	int ans = 0;
    	while(top[x] != top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		ans += Seg::asksum(1, dfn[top[x]], dfn[x]);
    		ans %= mod;
    		x = fa[top[x]];
    	}
    	if(dep[x] > dep[y]) swap(x, y);
    	ans += Seg::asksum(1, dfn[x], dfn[y]);
    	ans %= mod;
    	return ans % mod;
    }
    
    int main() {
    	n = read(), m = read(), root = read(), mod = read();
    	for(int i = 1; i <= n; i++) w[i] = read() % mod;
    	for(int i = 1; i < n; i++) {
    		int x = read(), y = read();
    		add_edge(x, y), add_edge(y, x);
    	}
    	dfs1(root, 0);
    	dfs2(root, root);
    	Seg::build(1, 1, n);
    	while(m--) { 
    		int opt = read(), x, y, z;
    		if(opt == 1) x = read(), y = read(), z = read() % mod, add_qwq(x, y, z);
    		if(opt == 2) x = read(), y = read(), cout << asksum_qwq(x, y) % mod << '
    ';
    		if(opt == 3) x = read(), z = read(), Seg::add(1, dfn[x], dfn[x] + siz[x] - 1, z);
    		if(opt == 4) x = read(), cout << Seg::asksum(1, dfn[x], dfn[x] + siz[x] - 1) % mod << '
    ';
    	}
    	return 0;
    }
    

    求LCA

    树剖求LCA

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 5e5 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, R;
    struct node { int to, nxt; } e[A << 1];
    int head[A], cnt, dep[A], son[A], dfn[A], siz[A], fa[A], top[A], tot;
    
    inline void add(int from, int to) {
    	e[++cnt].to = to;
    	e[cnt].nxt = head[from];
    	head[from] = cnt;
    }
    
    void prepare(int now, int fr) {
    	fa[now] = fr, dep[now] = dep[fr] + 1, siz[now] = 1;
    	for(int i = head[now]; i; i = e[i].nxt) {
    		int to = e[i].to;
    		if(to == fr) continue;
    		prepare(to, now); siz[now] += siz[to];
    		if(siz[to] > siz[son[now]]) son[now] = to;
    	}
    }
    
    void dfs(int now, int tp) {
    	top[now] = tp, dfn[now] = ++tot;
    	if(son[now]) dfs(son[now], tp);
    	for(int i = head[now]; i; i = e[i].nxt) {
    		int to = e[i].to;
    		if(to == fa[now] || to == son[now]) continue;
    		dfs(to, to);
    	}
    }
    
    inline int LCA(int x, int y) {
    	while(top[x] != top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		x = fa[top[x]];
    	}
    	if(dep[x] > dep[y]) swap(x, y);
    	return x;
    }
    
    int main() {
    	n = read(), m = read(), R = read();
    	for(int i = 1, x, y; i < n; i++) {
    		x = read(), y = read();
    		add(x, y), add(y, x);
    	} 
    	prepare(R, 0); dfs(R, R);
    	while(m--) {
    		int x = read(), y = read();
    		cout << LCA(x, y) << '
    ';
    	}
    	return 0;
    }
    

    倍增求LCA

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 5e5 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, R;
    struct node { int to, nxt; } e[A << 1];
    int head[A], cnt, dep[A], fa[A][23], lg[A];
    
    inline void add(int from, int to) {
    	e[++cnt].to = to;
    	e[cnt].nxt = head[from];
    	head[from] = cnt;
    }
    
    void dfs(int now, int fr) {
    	fa[now][0] = fr, dep[now] = dep[fr] + 1;
    	for(int i = head[now]; i; i = e[i].nxt) {
    		int to = e[i].to;
    		if(to == fr) continue;
    		dfs(to, now);
    	}
    }
    
    inline int LCA(int x, int y) {
    	if(dep[x] < dep[y]) swap(x, y);
    	for(int i = 20; i >= 0; i--) if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
    	if(x == y) return x;
    	for(int i = 20; i >= 0; i--) if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    	return fa[x][0];
    }
    
    int main() {
    	n = read(), m = read(), R = read(); lg[1] = 0;
    	for(int i = 2, x, y; i <= n; i++) {
    		x = read(), y = read();
    		add(x, y), add(y, x);
    		lg[i] = lg[i >> 1] + 1;
    	}
    	
    	dfs(R, 0); 
    	
    	for(int j = 1; (1 << j) <= n; j++) 
    		for(int i = 1; i <= n; i++)
    			fa[i][j] = fa[fa[i][j - 1]][j - 1];
    	
    	while(m--) {
    		int x = read(), y = read();
    		cout << LCA(x, y) << '
    ';
    	}
    	
    	return 0;
    }
    

    ST表

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, a[B], f[B][25], lg[B];
    
    inline int query(int l, int r) {
    	int k = lg[r - l + 1];
    	return max(f[l][k], f[r - (1 << k) + 1][k]);
    }
    
    int main() {
    	n = read(), m = read(); lg[0] = -1;
    	for(int i = 1; i <= n; i++) a[i] = read(), f[i][0] = a[i], lg[i] = lg[i >> 1] + 1;
    	for(int j = 1; (1 << j) <= n; j++) 
    		for(int i = 1; i <= n; i++)
    			f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
    	while(m--) {
    		int x = read(), y = read();
    		cout << query(x, y) << '
    ';
    	}
    	return 0;
    }
    
    

    数学/数论

    求逆元

    递推1~n的逆元

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 3e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, p;
    ll inv[B];
    
    int main() {
    	n = read(), p = read();
    	inv[1] = 1;
    	for(int i = 2; i <= n; i++) {
    		inv[i] = 1LL * (p - p / i) * inv[p % i] % p;
    	}
    	for(int i = 1; i <= n; i++) cout << inv[i] << '
    ';
    	return 0;
    }
    

    矩阵快速幂

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define int long long
    using namespace std;
    
    const int A = 1e2 + 11;
    const int B = 1e6 + 11;
    const int mod = 1e9 + 7;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x =  + (c ^ 48);
    	return x * f;
    }
    
    int n, k;
    struct matrix {
    	int a[A][A];
    	matrix() { memset(a, 0, sizeof(a)); }
    	void init() { for(int i = 1; i <= n; i++) a[i][i] = 1; }
    } ans, a;
    
    matrix operator * (const matrix &x, const matrix &y) {
    	matrix qwq;
    	for(int k = 1; k <= n; k++) 
    		for(int i = 1; i <= n; i++) 
    			for(int j = 1; j <= n; j++)
    				qwq.a[i][j] = (qwq.a[i][j] + x.a[i][k] * y.a[k][j] % mod) % mod;
    	return qwq; 
    }
    
    inline void power() {
    	while(k) {
    		if(k & 1) ans = ans * a;
    		a = a * a; k >>= 1;
    	}
    }
    
    signed main() {
    	n = read(), k = read();
    	for(int i = 1; i <= n; i++)
    		for(int j = 1; j <= n; j++) 
    			a.a[i][j] = read();
    	ans.init();
    	power();
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			cout << ans.a[i][j] << " ";
    		}
    		puts("");
    	}
    	return 0;
    }
    

    快速乘

    //知识点:快速乘
    /*
    By:Loceaner
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define int long long
    using namespace std;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    int a, b, p, ans;
    
    int mul(int a, int b, int mod) {
    	int res = 0;
    	while(b) {
    		if(b & 1) res = (res + a) % mod;
    		a = (a + a) % mod;
    		b >>= 1;
    	}
    	return res % mod;
    }
    
    signed main() {
    	a = read(), b = read(), p = read();
    	ans = mul(a, b, p);
    	cout << ans << '
    ';
    	return 0;
    }
    
    

    快速幂

    //知识点:快速幂 
    /*
    By:Loceaner
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define int long long
    using namespace std;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    int a, b, p, ans;
    
    int power(int a, int b, int mod) {
    	int res = 1;
    	while(b) {
    		if(b & 1) res = res * a % mod;
    		a = a * a % mod;
    		b >>= 1;
    	}
    	return res % mod;
    }
    
    signed main() {
    	a = read(), b = read(), p = read();
    	ans = power(a, b, p);
    	cout << ans << '
    ';
    	return 0;
    }
    

    埃氏筛

    void prime(int n) {
    	cnt = 0;
    	vis[0] = vis[1] = 1;
    	for(int i = 2; i <= n; ++i) {
    		if(!vis[i]) {
    			p[++cnt] = i;
    			for(int j = i * i; j <= n; j+=i) {
    				vis[j] = true;
    			}
    		}
    	}
    }
    

    线性筛

    int vis[N], p[N], cnt;
    
    void prepare() {
    	vis[0] = vis[1] = 1;
    	for(int i = 2; i <= n; i++) {
    		if(!vis[i]) p[++cnt] = i;
    		for(int j = 1; j <= cnt; j++) {
    			if(i * p[j] > n) break;
    			vis[i * p[j]] = 1;
    			if(i % p[j] == 0) break;
    		}
    	}
    }
    

    动态规划

    最长上升子序列

    普通二分

    //知识点:
    /*
    By:Loceaner
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    const int N = 10001;
    
    int f[N], a[N], n;
    int len = 1;
    
    int main() {
    	memset(f, 0x3f, sizeof(f));
    	n = read();
    	for(int i = 1; i <= n; i++) a[i] = read();
    	f[len] = a[1];
    	for(int i = 2; i <= n; i++) {
    		int l = 1, r = len, mid, rec;
    		if(a[i] > f[len]) f[++len] = a[i];
    		else {
    			while(l <= r) {
    				mid = (l + r) / 2;
    				if(f[mid] >= a[i]) rec = mid, r = mid - 1;
    				else l = mid + 1;
    			}
    			f[rec] = min(f[rec], a[i]);
    		}
    	}
    	for(int i = 1; i <= len; i++) cout << f[i] << " ";
    	cout << '
    ' << len << '
    '; 
    	return 0;
    }
    /*
    9
    7 2 1 5 6 4 3 8 9
    */
    
    

    lower_bound

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    const int N = 10001;
    
    int f[N], a[N], n;
    int len = 1;
    
    int main() {
    	memset(f, 0x3f, sizeof(f));
    	n = read();
    	for(int i = 1; i <= n; i++) a[i] = read();
    	f[1] = a[1];
    	for(int i = 2; i <= n; i++) {
    		if(a[i] > f[len]) f[++len] = a[i];
    		else { 
    			int p = lower_bound(f + 1, f + len + 1 , a[i]) - f;
    			f[p] = a[i];
    		}
    	}
    	for(int i = 1; i <= len; i++) cout << f[i] << " ";
    	cout << '
    ' << len << '
    ';
    	return 0;
    }
    

    最长公共子序列

    (n^2)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    const int N = 1011;
    
    int dp[N][N], a1[N], a2[N], n, m;
    
    int main() {
    	n = read();
    	for(int i = 1; i <= n; i++) a1[i] = read();
    	for(int i = 1; i <= n; i++) a2[i] = read();
    	for(int i = 1; i <= n; i++)
    		for(int j = 1; j <= n; j++) {
    			dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
    			if(a1[i] == a2[j]) dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);
    		}
    	cout << dp[n][n] << '
    ';
    	return 0;
    }
    

    图论

    tarjan

    #include <bits/stdc++.h>
    using namespace std;
    
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
        for( ; isdigit(c); c = getchar()) x = x * 10 + c - 48;
        return x * f;
    }
    
    const int N = 1011;
    
    struct node {
        int to, nxt;
    } e[N];
    
    int low[N], dfn[N], tot, topp = 0, sta[N], cnt, head[N];
    bool vis[N];
    
    inline void add(int from, int to) {
        e[++tot].to = to;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    void tarjan(int u) {
        dfn[u] = low[u] = ++cnt, sta[++topp] = u, vis[u] = 1;
        for(int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if(!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
            else if(vis[v]) low[u] = min(low[u], dfn[v]);
        }
        if(dfn[u] == low[u]) {
            do {
                cout << sta[topp] << ' ';
                vis[sta[topp--]] = 0;
            }while(u != sta[topp + 1]);
            cout << '
    ';
        }
    }
    
    int n, m;
    
    int main() {
        n = read(), m = read();
        for(int i = 1; i <= m; i++) {
            int u = read(), v = read();
            add(u, v);
        }
        for(int i = 1; i <= n; i++) 
            if(!dfn[i]) tarjan(i);
    }
    /*
    5 8
    1 2
    2 3
    3 6
    5 6
    1 4
    4 5
    5 1
    2 5
    */
    

    最小生成树

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 2e5 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    int n, m, fa[A], cnt, ans;
    struct node { int x, y, val; } e[A];
    int find(int x){ return fa[x] == x ? x : fa[x] = find(fa[x]); }
    bool cmp(node x, node y) { return x.val < y.val; }
    
    int main() {
    	n = read(), m = read();
    	for(int i = 1; i <= n; i++) fa[i] = i;
    	for(int i = 1; i <= m; i++) e[i].x = read(), e[i].y = read(), e[i].val = read();
    	sort(e + 1, e + 1 + m, cmp);
    	for(int i = 1; i <= m; i++) {
    		int dx = find(e[i].x), dy = find(e[i].y);
    		if(dx != dy) {
    			fa[dy] = dx;
    			ans += e[i].val;
    			cnt++;
    			if(cnt == n - 1) break;
    		}
    	}
    	cout << ans << '
    ';
    	return 0;
    }
    

    求树的直径

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
        for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
        return x * f;
    }
    
    const int M = 3e5 + 11;
    
    int n, cnt, k, ans, head[M], dep[M], vis[M];
    
    struct node {
        int nxt, to;
    } edge[M];
    
    void add(int from, int to) {
        edge[++cnt].nxt = head[from];
        edge[cnt].to = to;
        head[from] = cnt;
    }
    
    void dfs(int x, int fx) {
        vis[x] = 1;
        for(int i = head[x]; i; i = edge[i].nxt) {
            int to = edge[i].to;
            if(to == fx) continue;
            dep[to] = dep[x] + 1;
            if(ans < dep[to]) {
                ans = dep[to];
                k = to;
            }
            dfs(to, x);
        }
    }
    
    int main() {
        n = read();
        for(int i = 1; i < n; i++) {
            int x = read(), y = read();
            add(x, y), add(y, x);
            ans = 0, dep[x] = 0, memset(vis, 0, sizeof(vis)); dfs(x, 0);
            ans = 0, dep[k] = 0, memset(vis, 0, sizeof(vis)); dfs(k, 0);
            cout << ans << '
    ';
        }
        return 0;
    }
    

    二分图匹配

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e6 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, E, ans;
    struct node { int to, nxt; } e[A];
    int head[A], cnt, match[A], vis[A];
    
    inline void add(int from, int to) {
    	e[++cnt].to = to;
    	e[cnt].nxt = head[from];
    	head[from] = cnt;
    }
    
    bool dfs(int now) {
    	for(int i = head[now]; i; i = e[i].nxt) {
    		int to = e[i].to;
    		if(vis[to]) continue;
    		vis[to] = 1;
    		if(!match[to] || dfs(match[to])) {
    			match[to] = now;
    			return 1;
    		}
    	}
    	return 0;
    } 
    
    int main() {
    	n = read(), m = read(), E = read();
    	for(int i = 1, x, y; i <= E; i++) {
    		x = read(), y = read();
    		if(x > n || y > m) continue;
    		add(x, y);
    	}
    	for(int i = 1; i <= n; i++) {
    		memset(vis, 0, sizeof(vis));
    		if(dfs(i)) ans++;
    	}
    	cout << ans << '
    ';
    	return 0;
    }
    

    最短路

    堆优化dij

    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, dis[A], S;
    struct node { int to, nxt, val; } e[B];
    int head[A], cnt;
    
    inline void add(int from, int to, int val) {
    	e[++cnt].to = to;
    	e[cnt].val = val;
    	e[cnt].nxt = head[from];
    	head[from] = cnt;
    }
    
    struct edge {
    	int x, y;
    	bool operator < (const edge &qwq) const {
    		return y > qwq.y;
    	}
    };
    
    priority_queue<edge> Q;
    inline void ZDL() {
    	memset(dis, inf, sizeof(dis));
    	dis[S] = 0;
    	Q.push((edge) {S, 0});
    	while(!Q.empty()) {
    		int u = Q.top().x, d = Q.top().y; Q.pop();
    		if(d != dis[u]) continue;
    		for(int i = head[u]; i; i = e[i].nxt) {
    			int to = e[i].to;
    			if(dis[to] > dis[u] + e[i].val) {
    				dis[to] = dis[u] + e[i].val;
    				Q.push((edge) {to, dis[to]});
    			}
    		}
    	}
    }
    
    int main() {
    //	freopen("testdata.in", "r", stdin);
    	n = read(), m = read(), S = read();	
    	for(int i = 1, x, y, val; i <= m; i++) {
    		x = read(), y = read(), val = read();
    		add(x, y, val);
    	}
    	ZDL();
    	for(int i = 1; i <= n; i++) {
    		if(dis[i] == inf) cout << "2147483647 ";
    		else cout << dis[i] << " ";
    	}
    	return 0;
    }
    

    SPFA

    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, dis[A], S, vis[A];
    struct node { int to, nxt, val; } e[B];
    int head[A], cnt;
    
    inline void add(int from, int to, int val) {
    	e[++cnt].to = to;
    	e[cnt].val = val;
    	e[cnt].nxt = head[from];
    	head[from] = cnt;
    }
    
    queue <int> Q;
    inline void SPFA() {
    	memset(dis, inf, sizeof(dis));
    	dis[S] = 0, vis[S] = 1;
    	Q.push(S);
    	while(!Q.empty()) {
    		int u = Q.front(); Q.pop(); vis[u] = 0;
    		for(int i = head[u]; i; i = e[i].nxt) {
    			int to = e[i].to;
    			if(dis[to] > dis[u] + e[i].val) {
    				dis[to] = dis[u] + e[i].val;
    				if(!vis[to]) {
    					vis[to] = 1;
    					Q.push(to);
    				}
    			}
    		}
    	}
    }
    
    signed main() {
    	n = read(), m = read(), S = read();	
    	for(int i = 1, x, y, val; i <= m; i++) {
    		x = read(), y = read(), val = read();
    		add(x, y, val);
    	}
    	SPFA();
    	for(int i = 1; i <= n; i++) cout << dis[i] << " ";
    	return 0;
    }
    
    

    判负环

    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, dis[A], S = 1, vis[A], tot[A];
    struct node { int to, nxt, val; } e[B];
    int head[A], cnt;
    
    inline void add(int from, int to, int val) {
    	e[++cnt].to = to;
    	e[cnt].val = val;
    	e[cnt].nxt = head[from];
    	head[from] = cnt;
    }
    
    inline bool SPFA() {
    	memset(dis, inf, sizeof(dis));
    	dis[S] = 0, vis[S] = 1, tot[S] = 1;
    	queue <int> Q;
    	Q.push(S);
    	while(!Q.empty()) {
    		int u = Q.front(); Q.pop(); vis[u] = 0;
    		for(int i = head[u]; i; i = e[i].nxt) {
    			int to = e[i].to;
    			if(dis[to] > dis[u] + e[i].val) {
    				if(++tot[to] >= n) return 1;
    				dis[to] = dis[u] + e[i].val;
    				if(!vis[to]) {
    					vis[to] = 1;
    					Q.push(to);
    				}
    			}
    		}
    	}
    	return 0;
    }
    
    signed main() {
    	int T = read();
    	while(T--) {
    		memset(head, 0, sizeof(head));	
    		memset(vis, 0, sizeof(vis));
    		memset(tot, 0, sizeof(tot));
    		n = read(), m = read();
    		for(int i = 1, x, y, val; i <= m; i++) {
    			x = read(), y = read(), val = read();
    			add(x, y, val);
    			if(val >= 0) add(y, x, val);
    		}
    		if(SPFA()) puts("YE5");
    		else puts("N0");
    	}
    	return 0;
    }
    

    字符串

    (hash)

    /*
    By:Loceaner
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define ull unsigned long long
    using namespace std;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    const int N = 211;
    
    char pa[N][N], meng[N];
    int n, m, a[N], l[N], ans, cnt[N];
    ull p[N], cnm[N][N], sjp[N];
    
    
    bool query(int l1, int r1,int now) {
    	ull h1, h2;
    	h1 = sjp[r1] - sjp[l1 - 1] * p[r1 - l1 + 1];
    	h2 = cnm[now][l[now]];
    	return h1 == h2;
    }
    
    void work2() {//cnm
    	memset(sjp, 0, sizeof(sjp));
    	int len = strlen(meng + 1);
    	for(int i = 1; i <= len; i++) {
    		sjp[i] = sjp[i - 1] * 27 + meng[i] - 'a' + 1;
    	}
    	for(int i = 1; i <= m; i++) {
    		for(int j = 1; j <= len; j++) {
    			if(meng[j] == pa[i][1]) {
    				if(query(j, j + l[i] - 1, i)) ans += j * a[i];
    			}
    		}
    	}
    }
    
    int main() {
    	freopen("dream.in", "r", stdin);
    	freopen("dream.out", "w", stdout);
    	n = read(), m = read();
    	p[0] = 1;
    	for(int i = 1; i <= 200; i++) p[i] = p[i - 1] * 27ull;
    	for(int i = 1; i <= m; i++) scanf("%s", pa[i] + 1), l[i] = strlen(pa[i] + 1);
    	for(int i = 1; i <= m; i++)
    		for(int j = 1; j <= l[i]; j++)
    			cnm[i][j] = cnm[i][j - 1] * 27 + pa[i][j] - 'a' + 1;
    	for(int i = 1; i <= m; i++) a[i] = read();
    	for(int i = 1; i <= n; i++) scanf("%s", meng + 1), work2();
    	cout << ans << '
    ';
    	return 0;
    }
    

    KMP

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e6 + 11;
    const int B = 1e6 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, m, nxt[A];
    char s[A], t[A];
    
    void get_nxt() {
    	int p = 0;
    	for(int i = 2; i <= m; i++) {
    		while(p && t[i] != t[p + 1]) p = nxt[p];
    		if(t[i] == t[p + 1]) ++p;
    		nxt[i] = p;
    	}
    }
    
    int main() {
    	scanf("%s", s + 1); scanf("%s", t + 1);
    	n = strlen(s + 1), m = strlen(t + 1);
    	get_nxt();
    	int p = 0;
    	for(int i = 1; i <= n; i++) {
    		while(p && s[i] != t[p + 1]) p = nxt[p];
    		if(s[i] == t[p + 1]) {
    			++p;
    			if(p == m) {
    				cout << i - m + 1 << '
    ';
    				p = nxt[p];
    			}
    		}
    	}
    	for(int i = 1; i <= m; i++) cout << nxt[i] << " ";
    	return 0;
    }
    
  • 相关阅读:
    结对编程--黄金分割点游戏
    第一次单元测试,小紧张呢!
    Visual studio 2013 安装的漫长过程
    课后练习题:读程序
    进度条
    “啰嗦”的四则运算
    我与git“美妙”的一天
    结对编程(黄金分割点)
    Visual Studio 2015的安装和简单的测试
    软件工程学习体会
  • 原文地址:https://www.cnblogs.com/loceaner/p/11631856.html
Copyright © 2011-2022 走看看