CSP 2019 模板整合

qwq以下都为9.24后写的模板

ios::sync_with_stdio(false);
namespace IO{
	const int S = 1 << 20;
	char I[S + 1], *Is = I, *It = I, O[S + 1], *Ot = O;
	char gc() {return Is == It ? ((It = (Is = I) + fread(I, 1, S, stdin)) == I ? EOF: *Is++): *Is++;}
	void flush() {fwrite(O, 1, Ot - O, stdout), Ot = O;}
	void pc(char ch) {Ot == O + S? flush(), *Ot++ =ch: *Ot++ = ch;}
	struct flusher{ ~flusher(){flush();}}Flusher;
	#define getchar gc
	#define putchar pc
	inline int read() {
		int x = 0; char v = gc();
		for (; v < 48 || v > 57; v = gc());
		for (; v >= 48 && v <= 57; v = gc()) x = (x << 3) + (x << 1) + (v ^ 48);
		return x;
	}
	inline void write(int x) {
		static int buf[100], d;
		if (x == 0) pc('0');
		else {
			for (d = 0; x; x /= 10) buf[++d] = x % 10 + 48;
			while (d) pc((char)buf[d--]);
        }
	}
}
using namespace IO;

线性筛

bool su(int a){
    if(a==1) 
        return 0;
    if(a==2||a==3) 
        return 1;
    if(a%6!=1&&a%6!=5) 
        return 0;
    int temp=sqrt(a);
    for(int i=5;i<=temp;i+=6)
        if(a%i==0||a%(i+2)==0) 
            return 0;
    return 1;
}

快读

inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}

GCD

int GCD(int x, int y) {
	return y ? GCD(y, x % y) : x;
}

快速幂

inline int ksm(int a, int b) {
    int ans = 1;
    for (; b; b >>= 1, a = 1LL * a * a % Mo)
        if (b & 1) ans = 1LL * ans * a % Mo;
    return ans;
}

扩欧

void exgcd(int a, int b) {
    if (b == 0) {
        x = 1, y = 0;
        return;
    }
    exgcd(b, a % b);
    int k = x;
    x = y, y = k - a / b * y;
}
int exgcd(int a, int b, int &x, int &y) {
    if (!b) {
        x = 1, y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
struct Matrix {
    int n, a[N][N];

    Matrix(int _n = 0) {
        n = _n;
        memset(a, 0, sizeof(a));
    } 

    void operator ~(){
        for (int i = 0; i < n; i++)
            a[i][i] = 1;
    }

    Matrix operator *(const Matrix &b) const {
        Matrix sum(n);
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                for (int k = 0; k < n; k++)
                    sum.a[i][k] = (sum.a[i][k] + 1LL * a[i][j] * b.a[j][k] % Mo) % Mo;
        return sum;
    }
    
    Matrix operator^(long long p) const {
        Matrix sum(n), x = *this;
        ~sum;
        for (; p; p >>= 1, x = x * x)
            if (p & 1) sum = sum * x;
        return sum;
    }
} ;

CDQ

#include<bits/stdc++.h>
using namespace std;

const int N = 2e6 + 10;

int n, k, b[N], tot, f[N];

struct Node {
    int x, y, z, cnt, ans, id;
} a[N], c[N];

inline int read() {
    int x = 0, k = 1; char ch = getchar();
    for (; ch < 48 || ch > 57; ch = getchar()) k ^= (ch == '-');
    for (; ch >= 48 && ch <= 57; ch = getchar()) x = x * 10 + (ch ^ 48);
    return k ? x : -x;
}

inline bool cmp (Node x, Node y) {
    return x.x == y.x ? x.y == y.y ? x.z < y.z : x.y < y.y : x.x < y.x;
}

inline bool pd_equal(Node x, Node y) {
    return x.x != y.x || x.y != y.y || x.z != y.z;
}

inline void add(int x, int val) {
    for (; x <= k; x += (x & (-x)))
        b[x] += val;
}

inline int query(int x) {
    int ans = 0;
    for (; x; x -= (x & (-x)))
        ans += b[x];
    return ans;
}

void CDQ(int l, int r) {
    if (l == r)
        return;
    int mid = l + r >> 1;
    CDQ(l, mid), CDQ(mid + 1, r);
    for (int i = l, j = mid + 1, k = l; i <= mid || j <= r; k++) 
        if (j > r || (i <= mid && a[i].y <= a[j].y))
            c[k] = a[i++];
        else 
            c[k] = a[j++];
    for (int i = l; i <= r; i++)
        a[i] = c[i];
    for (int i = l; i <= r; i++)
        if (a[i].id <= mid)
            add(a[i].z, a[i].cnt);
        else 
            a[i].ans += query(a[i].z);
    for (int i = l; i <= r; i++)
        if (a[i].id <= mid)
            add(a[i].z, -a[i].cnt);
}

int main() {
    n = read(), k = read();
    for (int i = 1; i <= n; i++)
        a[i].x = read(), a[i].y = read(), a[i].z = read();
    std::sort(a + 1, a + 1 + n, cmp);
    for (int i = 1; i <= n; i++)
        if (!tot || pd_equal(a[i], a[i - 1]))  
            a[++tot] = a[i], a[tot].id = tot, a[tot].cnt = 1;
        else 
            a[tot].cnt++;
    CDQ(1, tot);
    for (int i = 1; i <= tot; i++)
        f[a[i].ans + a[i].cnt - 1] += a[i].cnt;
    for (int i = 0; i < n; i++)
        printf("%d\n", f[i]);
    return 0;
}

回文自动机(PAM) (9.24)

题目

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
char s[N];
int Len;
struct PAM{
	int last, cnt, len[N], fail[N], num[N], k, p, ch[N][26], p1, c[N];
	//char s[N];
	void init(char *s) {
		last = 0, cnt = 1, len[0] = 0, len[1] = -1, fail[0] = 1, fail[1] = 0, s[0] = 26;
	}
	void insert() {
		for (int i = 1; i <= Len; i++) {
			s[i] = (s[i] - 97 + k) % 26 + 97;
			c[i] = s[i] - 'a';
			p = last;
			while (s[i - len[p] - 1] != s[i])
				p = fail[p];
			if (!ch[p][s[i]]) {
				len[++cnt] = len[p] + 2, p1 = fail[p];
				while (s[i - len[p1] - 1] != s[i])
					p1 = fail[p1];
				fail[cnt] = ch[p1][s[i]];
				num[cnt] = num[fail[cnt]] + 1;
				ch[p][s[i]] = cnt;
			}
			last = ch[p][s[i]];
			printf("%d%c", num[last], (i == Len) ? '\n' : ' ');
			k = num[last];
			}
	}
} s1;
int main() {
	scanf("%s", s + 1);
	Len = strlen(s + 1);
	s1.init(s);
	s1.insert();
	return 0;
}

AC自动机 (9.25)

题目

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10, M = 160;
int n;
char s[M][N];
int trie[N][26], tot, endword[N], fail[N];
struct Node {
	int num, pos;
} Ans[N];
inline void Init(int x) {
	memset(trie[x], 0, sizeof(trie[x]));
	fail[x] = endword[x] = 0;
}
inline void Build_Trie(int gg) {
	int root = 0, len = strlen(s[gg] + 1);
	for (int j = 1; j <= len; j++) {
		if (!trie[root][s[gg][j] - 'a'])
			trie[root][s[gg][j] - 'a'] = ++tot, Init(tot);
		root = trie[root][s[gg][j] - 'a'];
	}
	endword[root] = gg;
}
inline void Get_Fail() {
	queue <int> q;
	for (int i = 0; i < 26; i++)
		if (trie[0][i]) {
			q.push(trie[0][i]);
			fail[trie[0][i]] = 0;
		}
	while (!q.empty()) {
		int now = q.front();
		q.pop();
		for (int i = 0; i < 26; i++)
			if (trie[now][i]) {
				fail[trie[now][i]] = trie[fail[now]][i];
				q.push(trie[now][i]);
			}
			else {
				trie[now][i] = trie[fail[now]][i];
			}
	}
}
inline int query() {
	int len = strlen(s[n + 1] + 1), ans = 0, now = 0;
	for (int i = 1; i <= len; i++) {
		now = trie[now][s[n + 1][i] - 'a'];
		for (int j = now; j; j = fail[j])
			Ans[endword[j]].num++;
	}
	return ans;
}
inline bool cmp(Node x, Node y) {
	return x.num > y.num || (x.num == y.num && x.pos < y.pos);
}
int main() {
	scanf("%d", &n);
	while (n != 0) {
		tot = 0;
		Init(0);
		for (int i = 1; i <= n; i++) {
			scanf("%s", s[i] + 1);
			Ans[i].num = 0, Ans[i].pos = i;
			Build_Trie(i);
		}
		fail[0] = 0;
		Get_Fail();
		scanf("%s", s[n + 1] + 1);
		query();
		std::sort(Ans + 1, Ans + 1 + n, cmp);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
		printf("%d\n%s\n", Ans[1].num, s[Ans[1].pos] + 1);
		for (int i = 2; i <= n; i++)
			if (Ans[1].num == Ans[i].num)
				printf("%s\n", s[Ans[i].pos] + 1);
			else 
				break;
		scanf("%d", &n);
	}
	return 0;
}

‘’

可持久化线段树(主席树) (9.25)

题目

(静态区间第k小)

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int l[N << 5], r[N << 5], cnt, sum[N << 5], a[N], b[N], c[N], n, q, m; 
inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}
inline int Build(int t, int w) {
	int now = ++cnt, mid = (t + w) >> 1;
	sum[now] = 0;
	if (t < w) {
		l[now] = Build(t, mid);
		r[now] = Build(mid + 1, w);
	}
	return now;
}
inline int add(int k, int t, int w, int x) {
	int now = ++cnt, mid = (t + w) >> 1;
	l[now] = l[k], r[now] = r[k], sum[now] = sum[k] + 1;
	if (t < w && x <= mid)
		l[now] = add(l[k], t, mid, x);
	else if (t < w && x > mid)
		r[now] = add(r[k], mid + 1, w, x);
	return now;
}
inline int ask(int L, int R, int t, int w, int x) {
	if (t >= w)
		return t;
	int mid = (t + w) >> 1, k = sum[l[R]] - sum[l[L]];
	if (k >= x)
		return ask(l[L], l[R], t, mid, x);
	else 
		return ask(r[L], r[R], mid + 1, w, x - k);
}
int main() {
	n = read(), q = read();
	for (int i = 1; i <= n; i++)
		b[i] = a[i] = read();
	std::sort(b + 1, b + 1 + n);
	m = unique(b + 1, b + 1 + n) - b - 1;
	c[0] = Build(1, m);
	for (int i = 1; i <= n; i++) {
		int now = lower_bound(b + 1, b  + 1 + m, a[i]) - b;
		c[i] = add(c[i - 1], 1, m, now);
	}
	for (int i = 1; i <= q; i++) {
		int x = read(), y = read(), z = read();
		printf("%d\n", b[ask(c[x - 1], c[y], 1, m, z)]);
	}
	return 0;
}

Manacher (9.25)

题目

#include<bits/stdc++.h>
using namespace std;
const int N = 31000000;
int len, hw[N], ans;
char s[N];
inline void Manacher() {
    int maxright = 0, mid = 0;
    for (int i = 1; i < len; i++) {
        if (i < maxright)
            hw[i] = std::min(hw[(mid << 1) - i], hw[mid] + mid - i);
        else 
            hw[i] = 1;
        while (s[i + hw[i]] == s[i - hw[i]])
            ++hw[i];
        if (hw[i] + i > maxright)
            maxright = hw[i] + i, mid = i;
    }
}
int main() {
    scanf("%s", s + 1);
    len = strlen(s + 1);
    for (int i = len; i >= 1; i--)
        s[i * 2] = s[i];
    s[0] = s[1] = '#';
    for (int i = 1; i <= len; i++)
        s[i * 2 + 1] = '#';
    s[len * 2 + 2] = 0;
    len = len * 2 + 2;
    Manacher();
    ans = 1;
    for (int i = 0; i < len; i++)
        ans = std::max(ans, hw[i]);
    printf("%d\n", ans - 1);
    return 0;
}

线性基 (9.26)

插入、判断、查询最大最小值、查询第\(k\)小值

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 110;
const int M = 50;
int n;
long long x, f[N + 10], a[M + 10], b[N + 10], ANS;
bool flag;
inline int read() {
    int x = 0, k = 1; char c = getchar();
    for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
    for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
    return k ? x : -x;
}   
inline long long read1() {
    long long x = 0, k = 1; char c = getchar();
    for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
    for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
    return k ? x : -x;
}
inline void Insert(long long x) {  //插入
    for (int i = M; i >= 0; i--)
        if (x & (1ll << i))
            if (!a[i]) {
                a[i] = x;
                return;
            }
            else x ^= a[i];
    flag = true;
}
inline bool check(long long x) {  //判断
    for (int i = M; i >= 0; i--) 
        if (x & (1ll << i)) {
            if (!a[i])
                return false;
            else 
                x ^= a[i];
        }
    return true;
}
inline long long Ask_max() {      //查询最大值
    long long maxx = 0;
    for (int i = M; i >= 0; i--)
        maxx = std::max(maxx, maxx ^ a[i]);
    return maxx;
}
inline long long Ask_min() {      //查询最小值
    if (flag)
        return 0;
    for (int i = 0; i <= M; i++)
        if (a[i])
            return a[i];
}
inline long long Ask_kth(long long x) {      //查询第k小值
    long long ans = 0;
    int cnt = 0;
    x -= flag;
    if (!x)
        return 0;
    for (int i = 0; i <= M; i++) {
        for (int j = i - 1; j >= 0; j--) 
            if (a[i] & (1ll << j))
                a[i] ^= a[j];
        if (a[i])
            b[cnt++] = a[i];
    }
    if (x >= (1ll << cnt))
        return -1;
    for (int i = 0; i < cnt; i++)
        if (x & (1ll << i))
            ans ^= b[i];
    return ans;
}
signed main() {
    n = read();
    for (int i = 1; i <= n; i++) 
        f[i] = read1();
    std::sort(f + 1, f + 1 + n);
    for (int i = 1; i <= n; i++) 
        if (check(f[i]))
            ANS += f[i];
        else 
            Insert(f[i]);
    printf("%lld\n", ANS);
    return 0;
}

高斯消元 (9.26)

题目

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int n;
double a[N][N];
inline bool Gauss(int n, int m) {
    for (int i = 1; i <= n; i++) {
        int maxx = i;
        for (int j = i + 1; j <= n; j++)
            if (fabs(a[j][i]) > fabs(a[maxx][i]))
                maxx = j;
        for (int j = 1; j <= m; j++)
            std::swap(a[i][j], a[maxx][j]);
        if (!a[i][i])
            return false;
        for (int j = 1; j <= n; j++)
            if (j != i) {
                double t = a[j][i] / a[i][i];
                for (int k = i + 1; k <= m; k++)
                    a[j][k] = a[j][k] - a[i][k] * t;
            }
    }
    return true;
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n + 1; j++)
            scanf("%lf", &a[i][j]);
    if (!Gauss(n, n + 1))
        return printf("No Solution\n"), 0;
    for (int i = 1; i <= n; i++)
        printf("%.2f\n", a[i][n + 1] / a[i][i]);
    return 0;
}

矩阵求逆 (9.26)

题目

#include<bits/stdc++.h>
using namespace std;
const int N = 1010, Mo = 1e9 + 7;
int n, a[N][N];
inline int ksm(int a, int b) {
    int ans = 1;
    for (; b; b >>= 1, a = 1LL * a * a % Mo)
        if (b & 1) ans = 1LL * ans * a % Mo;
    return ans;
}
inline bool Gauss(int n, int m) {
	for (int i = 1; i <= n; i++) {
		int maxx = i;
		for (int j = i + 1; j <= n; j++)
			if (fabs(a[j][i]) > fabs(a[maxx][i]))
				maxx = j;
		if (i != maxx)		
			for (int j = 1; j <= m; j++)
				std::swap(a[i][j], a[maxx][j]);
		if (!a[i][i])
			return false;
		int d = ksm(a[i][i], Mo - 2);
		for (int j = i; j <= m; j++)
			a[i][j] = 1LL * a[i][j] * d % Mo;
		for (int j = 1; j <= n; j++)
			if (j != i) {
				d = a[j][i];
				for (int k = i; k <= m; k++)
					a[j][k] = (a[j][k] - 1LL * a[i][k] * d % Mo + Mo) % Mo;
			}
	}
	return true;
}
signed main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++)
			scanf("%d", &a[i][j]);
		a[i][n + i] = 1;
	}
	if (!Gauss(n, n + n))
		return printf("No Solution\n"), 0;
	for (int i = 1; i <= n; i++)
		for (int j = n + 1; j <= n + n; j++)
			printf("%d%c", a[i][j], " \n"[j == n + n]);
	return 0;
}

普通莫队 (9.27)

SP3267 DQUERY - D-query

#include<bits/stdc++.h>
using namespace std;
const int N = 3e4 + 10, M = 2e6 + 10;
int n, m, now, be[M], a[M], cnt[M], ans[M];
struct Node {
	int l, r, id;
} q[M];
inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}
inline bool cmp(Node a, Node b) {
	return (be[a.l] ^ be[b.l]) ? be[a.l] < be[b.l] : ((be[a.l] & 1) ? a.r < b.r : a.r > b.r);
} 
int main() {
	n = read();
	int sz = sqrt(n), n1 = ceil((double)n / sz);
	for (int i = 1; i <= n1; i++)
		for (int j = (i - 1) * sz + 1; j <= i * sz; j++)
			be[j] = i;
	for (int i = 1; i <= n; i++)
		a[i] = read();
	m = read();
	for (int i = 1; i <= m; i++)
		q[i].l = read(), q[i].r = read(), q[i].id = i;
	std::sort(q + 1, q + 1 + m, cmp);
	int L = 1, R = 0;
	for (int i = 1; i <= m; i++) {
		int l = q[i].l, r = q[i].r;
		while (L < l)
			now -= !--cnt[a[L++]];
		while (L > l)
			now += !cnt[a[--L]]++;
		while (R < r)
			now += !cnt[a[++R]]++;
		while (R > r)
			now -= !--cnt[a[R--]];
		ans[q[i].id] = now;
	}
	for (int i = 1; i <= m; i++)
		printf("%d\n", ans[i]);
	return 0;
}

带修莫队 (9.27)

题目

#include<bits/stdc++.h>
using namespace std;
const int N = 3e4 + 10, M = 2e6 + 10;
int n, m, now, be[M], a[M], cnt[M], ans[M], cntc, cntq;
char ch;
struct Query {
	int l, r, id, time;
} q[M];
struct Replace {
	int pos, color;
} c[M];
inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}
inline bool cmp(Query a, Query b) {
	return (be[a.l] ^ be[b.l]) ? be[a.l] < be[b.l] : ((be[a.r] ^ be[b.r]) ? be[a.r] < be[b.r] : a.time < b.time);
} 
int main() {
	n = read(), m = read();
	int sz = pow(n, 2.0 / 3.0), n1 = ceil((double)n / sz);
	for (int i = 1; i <= n1; i++)
		for (int j = (i - 1) * sz + 1; j <= i * sz; j++)
			be[j] = i;
	for (int i = 1; i <= n; i++)
		a[i] = read();
	for (int i = 1; i <= m; i++) {
		scanf("%c", &ch);
		while (ch != 'Q' && ch != 'R')
			scanf("%c", &ch);
		if (ch == 'Q') {
			q[++cntq].l = read(), q[cntq].r = read(), q[cntq].time = cntc, q[cntq].id = cntq;
		}
		else if (ch == 'R') {
			c[++cntc].pos = read(), c[cntc].color = read();
		}
	}
	std::sort(q + 1, q + 1 + cntq, cmp);
	int L = 1, R = 0, Time = 0;
	for (int i = 1; i <= m; i++) {
		int l = q[i].l, r = q[i].r, time = q[i].time;
		while (L < l)
			now -= !--cnt[a[L++]];
		while (L > l)
			now += !cnt[a[--L]]++;
		while (R < r)
			now += !cnt[a[++R]]++;
		while (R > r)
			now -= !--cnt[a[R--]];
		while (Time < time) {
			Time++;
			if (l <= c[Time].pos && r >= c[Time].pos)
				now -= !--cnt[a[c[Time].pos]] - !cnt[c[Time].color]++;
			std::swap(a[c[Time].pos], c[Time].color);
		}
		while (Time > time) {
			if (l <= c[Time].pos && r >= c[Time].pos)
				now -= !--cnt[a[c[Time].pos]] - !cnt[c[Time].color]++;
			std::swap(a[c[Time].pos], c[Time].color);
			Time--;
		}
		ans[q[i].id] = now;
	}
	for (int i = 1; i <= cntq; i++)
		printf("%d\n", ans[i]);
	return 0;
}

折半搜索 (9.30)

[CEOI2015 Day2]世界冰球锦标赛

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10, M = 1 << 21;
int n;
long long aa[N], m;
long long suma[M], sumb[M], cnta, cntb;
long long ans;
inline int read() {
    int x = 0, k = 1; char c = getchar();
    for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
    for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
    return k ? x : -x;
}
inline long long read1() {
    long long x = 0, k = 1; char c = getchar();
    for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
    for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
    return k ? x : -x;
}
void dfs(int l, int r, long long sum, long long a[], long long &cnt) {
    if (sum > m)
        return;
    if (l > r) {
        a[++cnt] = sum;
        return;
    }
    dfs(l + 1, r, sum + aa[l], a, cnt);
    dfs(l + 1, r, sum, a, cnt);
}
signed main() {
    n = read(), m = read1();
    for (int i = 1; i <= n; i++)
        aa[i] = read1();
    dfs(1, n >> 1, 0, suma, cnta);
    dfs((n >> 1) + 1, n, 0, sumb, cntb);
    std::sort(suma + 1, suma + 1 + cnta);
    for (int i = 1; i <= cntb; i++)
        ans += upper_bound(suma + 1, suma + 1 +cnta, m - sumb[i]) - suma - 1;
    printf("%lld", ans);
    return 0;
}

树链剖分 (9.30)

题目

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, M = N << 2;
int n, m, r, Mo, num, from[N], nxt[N], to[N], w[N], w1[N], a[M], lazy[M];
int son[N], id[N], father[N], depth[N], size[N], top[N], cnt, res;
inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}
inline void add(int x, int y) { // build tree
	to[++num] = y, nxt[num] = from[x], from[x] = num;
}
void dfs1(int x, int fa, int deep) {
	depth[x] = deep, father[x] = fa, size[x] = 1;
	int maxx = -1; // find height son
	for (int i = from[x]; i; i = nxt[i]) {
		int y = to[i];
		if (y == fa) // father
			continue;
		dfs1(y, x, deep + 1);
		size[x] += size[y];
		if (size[y] > maxx)
			son[x] = y, maxx = size[y];
	}
}
void dfs2(int x, int Top) { // link top
	id[x] = ++cnt; // new number
	w1[cnt] = w[x]; // new value
	top[x] = Top;
	if (!son[x]) return; //no sum
	dfs2(son[x], Top);
	for (int i = from[x]; i; i = nxt[i]) {
		int y = to[i];
		if (y == father[x] || y == son[x]) // father or height son
			continue;
		dfs2(y, y); // light son -> link top
	}
}

/*********Segment Tree***********/
inline void pushdown(int x, int y) {
	int l = x << 1, r = x << 1 | 1;
	lazy[l] += lazy[x], lazy[r] += lazy[x];
	a[l] = (a[l] + lazy[x] * (y - (y >> 1))) % Mo;
	a[r] = (a[r] + lazy[x] * (y >> 1)) % Mo;
	lazy[x] = 0;	
}
void build(int x, int l, int r) {
	if (l == r) {
		a[x] = w1[l] % Mo;
		return;
	}
	build(x << 1, l, l + r >> 1);
	build(x << 1 | 1, (l + r >> 1) + 1, r);
	a[x] = (a[x << 1] + a[x << 1 | 1]) % Mo;
}
void query(int x, int l, int r, int L, int R) {
	if (L <= l && R >= r) {
		res = (res + a[x]) % Mo;
		return;
	}
	if (lazy[x])
		pushdown(x, r - l + 1);
	if (L <= (l + r >> 1))
		query(x << 1, l, l + r >> 1, L, R);
	if (R > (l + r >> 1))
		query(x << 1 | 1, (l + r >> 1) + 1, r, L, R);
}

void update(int x, int l, int r, int L, int R, int k) {
	if (L <= l && R >= r) {
		lazy[x] += k, a[x] += k * (r - l + 1);
		return;
	}
	if (lazy[x]) pushdown(x, r - l + 1);
	if (L <= (l + r >> 1))
		update(x << 1, l, l + r >> 1, L, R, k);
	if (R > (l + r >> 1))
		update(x << 1 | 1, (l + r >> 1) + 1, r, L, R, k);
	a[x] = (a[x << 1] + a[x << 1 | 1]) % Mo;
}
/*********Segment Tree***********/

inline void addroad(int x, int y, int k) {
	k %= Mo;
	while (top[x] != top[y]) { // not same link
		if (depth[top[x]] < depth[top[y]])
			std::swap(x, y);
		update(1, 1, n, id[top[x]], id[x], k);
		x = father[top[x]];
	}
	if (depth[x] > depth[y])
		std::swap(x, y);
	update(1, 1, n, id[x], id[y], k);
}
inline int sumroad(int x, int y) {
	int ans = 0;
	while (top[x] != top[y]) {
		if (depth[top[x]] < depth[top[y]])
			std::swap(x, y);
		res = 0;
		query(1, 1, n, id[top[x]], id[x]);
		ans = (ans + res) % Mo;
		x = father[top[x]];
	}
	if (depth[x] > depth[y])
		std::swap(x, y);
	res = 0;
	query(1, 1, n, id[x], id[y]);
	return (ans + res) % Mo;
}
inline int sumson(int x) {
	res = 0;
	query(1, 1, n, id[x], id[x] + size[x] - 1);
	return res;
}
inline void addson(int x, int k) {
	update(1, 1, n, id[x], id[x] + size[x] - 1, k);
}
int main() {
	n = read(), m = read(), r = read(), Mo = read();
	for (int i = 1; i <= n; i++)
		w[i] = read();
	for (int i = 1; i < n; i++) {
		int x = read(), y = read();
		add(x, y), add(y, x);
	}
	dfs1(r, 0, 1);
	dfs2(r, r);
	build(1, 1, n);
	while (m--) {
		int opt = read(), x = read();
		if (opt == 1) {
			int y = read(), z = read();
			addroad(x, y, z);   // (x - y) path -> add z
		}
		else if (opt == 2) {
			int y = read();
			printf("%d\n", sumroad(x, y)); // (x - y) path -> sum
		}
		else if (opt == 3) {
			int y = read();
			addson(x, y); // subtree -> add z
		}
		else if (opt == 4) 
			printf("%d\n", sumson(x)); // subtree -> sum
	}
	return 0;
}

匈牙利算法 (10.2)

题目

#include<bits/stdc++.h>
using namespace std;
const int N = 2010;
int n, m, e, Match[N << 1], ans, ask[N << 1], head[N], cnt;
struct Node {
    int to, nxt;
} edge[N * N];
inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}
inline void add(int u, int v) {
    edge[++cnt] = (Node) {v, head[u]}, head[u] = cnt;
}
inline bool found(int x) {
    for (int i = head[x]; i; i = edge[i].nxt) {
        int y = edge[i].to;
        if (ask[y]) continue;
        ask[y] = 1;
        if (!Match[y] || found(Match[y])) {
            Match[y] = x;
            return true;
        }
    }
    return false;
}
inline void match() {
    for (int i = 1; i <= n; i++) {
        memset(ask, 0, sizeof(ask));
        if (found(i))
            ans++;
    }
}
int main() {
    n = read(), m = read(), e = read();
    for (int i = 1; i <= e; i++) {
        int u = read(), v = read();
        if (v > m || u > n)
            continue;
        add(u, v + n);
    }
    match();
    printf("%d\n", ans);
    return 0;
}

Hopcroft-Karp (未)

//不是我的代码
/*
dx[i]表示左集合i顶点的距离编号
dy[i]表示右集合i顶点的距离编号
mx[i]表示左集合顶点所匹配的右集合顶点序号
my[i]表示右集合i顶点匹配到的左集合顶点序号
*/
#include <bits/stdc++.h>
#define N 1005
#define M 1000005
using namespace std;
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[25];int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
struct node{
    int to,next;
}e[M];
int head[N],tot=0;
inline void add(register int u,register int v)
{
    e[++tot]=(node){v,head[u]};
    head[u]=tot;
}
int n,m,es,ans;
int dx[N],dy[N],mx[N],my[N],vis[N],dis;
inline bool bfs()
{
    queue<int> q;
    dis=1926081700;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(register int i=1;i<=n;++i)
        if(mx[i]==-1)
        {
            q.push(i);
            dx[i]=0;
        }
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(dx[u]>dis)
            break;
        for(register int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(dy[v]==-1)
            {
                dy[v]=dx[u]+1;
                if(my[v]==-1)
                    dis=dy[v];
                else
                {
                    dx[my[v]]=dy[v]+1;
                    q.push(my[v]);
                        }       
            }   
        }
    }
    return dis!=1926081700;
}
inline bool dfs(register int u)
{
    for(register int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(vis[v]||(dy[v]!=dx[u]+1))
            continue;
        vis[v]=1;
        if(my[v]!=-1&&dy[v]==dis)
            continue;
        if(my[v]==-1||dfs(my[v]))
        {
            my[v]=u;
            mx[u]=v;
            return true;
        }
    }
    return false;
}
inline void match()
{
    memset(mx,-1,sizeof(mx));
    memset(my,-1,sizeof(my));
    while(bfs())
    {
        memset(vis,0,sizeof(vis));
        for(register int i=1;i<=n;++i)
            if(mx[i]==-1&&dfs(i))
                ++ans;
    }
}
int main()
{
    n=read(),m=read(),es=read();
    while(es--)
    {
        int u=read(),v=read();
        if(v>m)
            continue;
        add(u,v);   
    }   
    match();
    write(ans);
    return 0;
} 

Kuhn-Munkras (10.5)

hdu2255

#include<bits/stdc++.h>
using namespace std;
const int N = 110, INF = 0x3f3f3f3f;
bool tfg[N], tfb[N];
int b[N], g[N], a[N][N], match[N], slack[N], n;
inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}
bool pd(int x) {
    tfg[x] = true;
    for (int i = 1; i <= n; i++) {
        if (tfb[i])
            continue;
        int t = b[i] + g[x] - a[x][i];
        if (t == 0) {
            tfb[i] = true;
            if (match[i] == -1 || pd(match[i])) {
                match[i] = x;
                return true;
            }
        }
        else 
            slack[i] = std::min(slack[i], t);
    }
    return false;
}
inline void KM() {
    memset(match, -1, sizeof(match));
    memset(b, 0, sizeof(b));
    for (int i = 1; i <= n; i++) {
        g[i] = a[i][1];
        for (int j = 2; j <= n; j++)
            g[i] = std::max(g[i], a[i][j]);
    }
    for (int i = 1; i <= n; i++) {
        fill(slack + 1, slack + n + 1, INF);
        while (true) {
            memset(tfb, false, sizeof(tfb));
            memset(tfg, false, sizeof(tfg));    
            if (pd(i))
                break;
            int d = INF;
            for (int j = 1; j <= n; j++)
                if (!tfb[j])
                    d = std::min(d, slack[j]);
            for (int j = 1; j <= n; j++) {
                if (tfg[j])
                    g[j] -= d;
                if (tfb[j]) b[j] += d; else slack[j] -= d;
            }
        }
    }
}
int main() {
    n =  read();
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            a[i][j] = read();
    KM();
    int ans = 0;
    for (int i = 1; i <= n; i++)
        ans += a[match[i]][i];
    printf("%d\n", ans);
    return 0;
}

动态dp (10.7)

题目

yyb巨佬博客

#include<bits/stdc++.h>
using namespace std;

const int INF = -0x3f, N = 1e5 + 10, M = 4e5 + 10;

int n, m, cnt, head[N], to[M], nxt[M], siz[N], fa[N], val[N], son[N], cnt1, id[N], dfn[N], End[N], top1[N], f[N][2], L[N << 2], R[N << 2];

struct Matrix {
	int mat[2][2];

	Matrix() {
		memset(mat, INF, sizeof(mat));
	}

	inline Matrix operator * (Matrix b) {
		Matrix a;
		for (int i = 0; i < 2; i++)
			for (int j = 0; j < 2; j++)
				for (int k = 0; k < 2; k++)
					a.mat[i][j] = std::max(a.mat[i][j], mat[i][k] + b.mat[k][j]);
		return a;
	}

} Val[N << 2], a[N << 2];

inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}

inline void add(int x, int y) {
	to[++cnt] = y, nxt[cnt] = head[x], head[x] = cnt;
}

void dfs1(int x) {
	siz[x] = 1;
	for (int i = head[x]; i; i = nxt[i]) {
		int y = to[i];
		if (y == fa[x])
			continue;
		fa[y] = x;
		dfs1(y);
		siz[x] += siz[y];
		if (siz[y] > siz[son[x]]) // height son
			son[x] = y;
	}
}

void dfs2(int x, int Top) {
	id[x] = ++cnt1, dfn[cnt1] = x, top1[x] = Top, End[Top] = std::max(End[Top], cnt1);
	f[x][0] = 0, f[x][1] = val[x];
	Val[x].mat[0][0] = Val[x].mat[0][1] = 0, Val[x].mat[1][0] = val[x];
	if (son[x] != 0) {
		dfs2(son[x], Top);
		f[x][0] += std::max(f[son[x]][0], f[son[x]][1]);
		f[x][1] += f[son[x]][0];
	}
	for (int i = head[x]; i; i = nxt[i]) {
		int y = to[i];
		if (y== fa[x] || y == son[x])
			continue;
		dfs2(y, y);
		f[x][0] += std::max(f[y][0], f[y][1]), f[x][1] += f[y][0];
		Val[x].mat[0][0] += std::max(f[y][0], f[y][1]);
		Val[x].mat[0][1] = Val[x].mat[0][0], Val[x].mat[1][0] += f[y][0];
	}
}

void Build(int l, int r, int x) {
	L[x] = l, R[x] = r;
	if (L[x] == R[x]) {
		a[x] = Val[dfn[L[x]]];
		return;
	}
	Build(L[x], L[x] + R[x] >> 1, x << 1);
	Build((L[x] + R[x] >> 1) + 1, R[x], x << 1 | 1);
	a[x] = a[x << 1] * a[x << 1 | 1];
}

void update(int x, int i) {
	if (L[i] == R[i]) {
		a[i] = Val[dfn[x]];
		return;
	}
	if (x <= (L[i] + R[i] >> 1))
		update(x, i << 1);
	else
		update(x, i << 1 | 1);
	// update(x, (x <= (L[i] + R[i] >> 1)) ? (i << 1) : (i << 1 | 1));
	a[i] = a[i << 1] * a[i << 1 | 1];
}

Matrix query(int l, int r, int x) {
	if (L[x] == l && R[x] == r)
		return a[x];
	int mid = L[x] + R[x] >> 1;
	if (r <= mid) return query(l, r, x << 1);
	else if (l > mid) return query(l, r, x << 1 | 1);
	else return query(l, mid, x << 1) * query(mid + 1, r, x << 1 | 1);
}

void update_path(int x, int y) {
	Val[x].mat[1][0] += y - val[x], val[x] = y;
	Matrix a, b;
	while (x != 0) {
		a = query(id[top1[x]], End[top1[x]], 1);
		update(id[x], 1);
		b = query(id[top1[x]], End[top1[x]], 1), x = fa[top1[x]];
		Val[x].mat[0][0] += std::max(b.mat[0][0], b.mat[1][0]) - std::max(a.mat[0][0], a.mat[1][0]), Val[x].mat[0][1] = Val[x].mat[0][0];
		Val[x].mat[1][0] += b.mat[0][0] - a.mat[0][0];
	}
}

int main() {
	n = read(), m = read();
	for (int i = 1; i <= n; i++)
		val[i] = read();
	for (int i = 1; i < n; i++) {
		int x = read(), y = read();
		add(x, y), add(y, x);
	}
	dfs1(1);
	dfs2(1, 1);
	Build(1, n, 1);
	for (int i = 1; i <= m; i++) {
		int x = read(), y = read();
		update_path(x, y);
		Matrix ans = query(id[1], End[1], 1);
		printf("%d\n", std::max(ans.mat[0][0], ans.mat[1][0]));
	}
	return 0;
}

缩点(10.8)

CF734E Anton and Tree

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;

int n, color[N];
vector<int> a[N];

inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}

pair<int, int> dfs(int x, int fa, int depth) {
    int sz = a[x].size();
    pair<int, int> tmp = make_pair(depth, x);
    for (int i = 0; i < sz; i++) {
        int y = a[x][i];
        if (y == fa)
            continue;
        if(color[y] != color[x])
            tmp = std::max(tmp, dfs(y, x, depth + 1));
        else 
            tmp = std::max(tmp, dfs(y, x, depth));
    }
    return tmp;
}

int main() {
    n = read();
    for (int i = 1; i <= n; i++)
        color[i] = read();
    for (int i = 1; i < n; i++) {
        int x = read(), y = read();
        a[x].push_back(y), a[y].push_back(x);
    }
    pair<int, int> tmp = dfs(1, -1, 0);
    tmp = dfs(tmp.second, -1, 0);
    printf("%d\n", tmp.first + 1 >> 1);
}

Lucas (10.9)

inline long long ksm(long long a, long long b) {
    long long ans = 1;
    a = a % Mo;
    for (; b; b >>= 1, a = a * a % Mo)
        if (b & 1) ans = ans * a % Mo;
    return ans;
}

inline long long C(long long n, long long m) {
    if (m > n) return 0;
    long long a = 1, b = 1;
    for (long long i = 1; i <= m; i++)
        a = a * (n + i - m) % Mo, b = b * i % Mo;
    return a * ksm(b, Mo - 2) % Mo;
}

inline long long Lucas(long long n, long long m) {
    long long ans = 1;
    for (; n && m; n /= Mo, m /= Mo)
        ans = ans * C(n % Mo, m % Mo);
    return ans;
}

Simpson 1(10.9)

题目

#include<bits/stdc++.h>
using namespace std;

const double Eps = 1e-6;

double a, b, c, d, L, R;

inline double f(double x) {
    return (c * x + d) / (a * x + b);
}

inline double Simpson(double L, double R) {
    double mid = (L + R) / 2;
    return ((R - L) * (f(L) + f(R) + 4 * f(mid))) / 6.0;
}

inline double Solve(double L, double R, double eps, double ans) {
    double mid = (L + R) / 2;
    double l = Simpson(L, mid), r = Simpson(mid, R);
    if (fabs(l + r - ans) <= eps * 15)
        return l + r + (l + r - ans) / 15;
    return Solve(L, mid, eps / 2, l) + Solve(mid, R, eps / 2, r);
}

inline double Solve(double L, double R, double eps) {
    return Solve(L, R, eps, Simpson(L, R));
}

int main() {
    scanf("%lf%lf%lf%lf%lf%lf", &a, &b, &c, &d, &L, &R);
    printf("%.6f", Solve(L, R, Eps));
    return 0;
}

Simpson 2 (10.10)

#include<bits/stdc++.h>
using namespace std;

const double Eps = 1e-8;

double a, b, c, d, L, R;

inline double f(double x) {
    return pow(x, a / x - x);
}

inline double Simpson(double L, double R) {
    double mid = (L + R) / 2;
    return ((R - L) * (f(L) + f(R) + 4 * f(mid))) / 6.0;
}

inline double Solve(double L, double R, double eps, double ans) {
    double mid = (L + R) / 2;
    double l = Simpson(L, mid), r = Simpson(mid, R);
    if (fabs(l + r - ans) <= eps * 15)
        return l + r + (l + r - ans) / 15;
    return Solve(L, mid, eps / 2, l) + Solve(mid, R, eps / 2, r);
}

inline double Solve(double a, double b) {
    return Solve(a, b, Eps, Simpson(a, b));
}

int main() {
    scanf("%lf", &a);
    if (a < 0) 
        return puts("orz"), 0;
    printf("%.5f", Solve(Eps, 20.0));
    return 0;
}

\(\mathcal{01trie}\)

题目

#include<bits/stdc++.h>
#define pow(x, i) (x >> i)
using namespace std;

const int N = 6e6 + 10, M = 30;

int cnt[N], trie[N][2], tot = 1, n;

inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}

inline void add(int x, int dg) {
    int p = 1;
    for (int i = M; i >= 0; --i) {
        if (dg == 1) trie[p][(pow(x, i) & 1)] = (trie[p][(pow(x, i) & 1)] != 0) ? trie[p][(pow(x, i) & 1)] : (++tot);
        p = trie[p][(pow(x, i) & 1)], cnt[p] += dg;
    }
}

inline int ask(int x, int y) {
    int p = 1;
    int sum = 0;
    for (int i = M; i >= 0; i--) {
        int t = (pow(y, i) & 1), t1 = (pow(x, i) & 1);
        if (t)
            sum += cnt[trie[p][t1]], p = trie[p][t1 ^ 1];
        else 
            p = trie[p][t1];
    }
    return sum;
}

int main() {
    n = read();
    while (n--) {
        int opt = read(), x = read();
        if (opt == 1)
            add(x, 1);
        else if (opt == 2)
            add(x, -1);
        else if (opt == 3) {
            int y = read();
            printf("%d\n", ask(x, y));
        }
    }
    return 0;
}

树的重心

#include<bits/stdc++.h>
using namespace std;

const int N =  3e5 + 10;

struct Node {
    int to, nxt;
} edge[N << 1];

int cnt, n, m, Fa[N], sz[N], ans[N], head[N];

inline int read() {
    int x = 0, k = 1; char c = getchar();
    for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
    for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
    return k ? x : -x;
}

inline void Build(int x, int y) {
    edge[++cnt].to = x, edge[cnt].nxt = head[y], head[y] = cnt;
}

void dfs(int x, int fa) {
    int res = 0;
    sz[x] = 1,  ans[x] = x;
    for (int i = head[x]; i; i = edge[i].nxt) {
        int y = edge[i].to;
        if (y == fa)
            continue;
        dfs(y, x);
        sz[x] += sz[y], res = (sz[y] > sz[res]) ? y : res;
    }

    if ((sz[res] << 1) > sz[x])
        for (ans[x] = ans[res]; ((sz[x] - sz[ans[x]]) << 1) > sz[x]; ans[x] = Fa[ans[x]]);
}

int main() {
    n = read(), m = read();
    for (int i = 2; i <= n; i++) {
        Fa[i] = read();
        Build(i, Fa[i]);
        Build(Fa[i], i);
    }

    dfs(1, 0);

    while (m--) {
        int x = read();
        printf("%d\n", ans[x]);
    }
    return 0;
}

二分图多重匹配(未)

链接

2-SAT

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>

const int N = 1e6;

int n, m, num, cnt, NUM, u1, v1, u2, v2, dfn[N << 2], low[N << 2], Stack[N << 2], f[N << 2], head[N << 2], a, x, b, y, tot;
bool vis[N << 2];

struct Node {
    int to, nxt, from;
} edge[N << 2];

inline int read() {
	int x = 0, k = 1; char c = getchar();
	for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
	for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
	return k ? x : -x;
}

void Tarjan(int x, int fa) {
    dfn[x] = low[x] = ++num, vis[x] = true, Stack[++cnt] = x;
    bool tf = 0;
    for (int i = head[x]; i; i = edge[i].nxt) {
        int y = edge[i].to;
        if (y == fa && !tf) {
            tf = 1;
            continue;
        }
        if (!dfn[y]) {
            Tarjan(y, x);
            low[x] = std::min(low[x], low[y]);
        }
        else if (!f[y]) {
            low[x] = std::min(low[x], dfn[y]);
        }
    }
    if (dfn[x] == low[x]) {
        NUM++;
        for (; Stack[cnt] != x; ) f[Stack[cnt]] = NUM, vis[Stack[cnt]] = 0, --cnt;
        f[Stack[cnt]] = NUM, vis[Stack[cnt]] = 0;
        cnt--;
    }
}

inline void add(int x, int y) {
    edge[++tot].to = y, edge[tot].from = x, edge[tot].nxt = head[x], head[x] = tot;
}

int main() {
    n = read(), m = read();
    for (int i = 1; i <= m; i++) {
        a = read(), x = read(), b = read(), y = read();
        if (x == 0)
            u1 = a + n, v2 = a;
        else if (x == 1)
            u1 = a, v2 = a + n;
        if (y == 0)
            v1 = b, u2 = b + n;
        else if (y == 1)
            v1 = b + n, u2 = b;
        add(u1, v1), add(u2, v2);
    }
    for (int i = 1; i <= 2 * n; i++)
        if (!dfn[i])
            Tarjan(i, 0);
    for (int i = 1; i <= n; i++) 
        if (f[i] == f[i + n]) {
            printf("IMPOSSIBLE\n");
            return 0;
        }
    printf("POSSIBLE\n");
    for (int i = 1; i <= n; i++) 
        printf("%d ", f[i] > f[i + n] ? 1 : 0);
    return 0;
}

dij + Tarjan + 拓扑

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 3e5 + 10, INF = 1e16 + 10;
int In[N], dis[N], dis1[N], cnt, cnt1, head[N], head1[N], dfn[N], f[N], sum, Stack[N], low[N], n, m, ans[N], num; 
bool vis[N];

struct node {
    int to, nxt, e, p, from;
    bool tf;
} E[N], E1[N];

struct Node {
    int e, y;
    bool operator <(const Node &x) const {
        return e > x.e;
    }  
} ;
inline int read() {
    int x = 0, k = 1; char ch = getchar();
    for (; ch < 48 || ch > 57; ch = getchar()) k ^= (ch == '-');
    for (; ch >= 48 && ch <= 57; ch = getchar()) x = x * 10 + (ch ^ 48);
    return k ? x : -x;
}
inline void Build(int x, int y, int e, int p) {
    E[++cnt].to = y, E[cnt].from = x, E[cnt].nxt = head[x], head[x] = cnt, E[cnt].e = e, E[cnt].p = p, E[cnt].tf = true;
}
inline void Build1(int x, int y, int e, int p) {
    E1[++cnt1].to = x, E1[cnt1].from = y, E1[cnt1].nxt = head1[y], head1[y] = cnt1, E1[cnt1].e = e, E1[cnt1].p = p, E1[cnt1].tf = true;
}
inline void Build2(int from, int to, int p) {
    E1[++cnt1].to = to, E1[cnt1].from = from, E1[cnt1].nxt = head1[from], head1[from] = cnt1, E1[cnt1].p = p; 
}
priority_queue<Node> q;
void Tarjan(int x) {
    dfn[x] = low[x] = ++num, Stack[++sum] = x;
    for (int i = head[x]; i; i = E[i].nxt) 
        if (E[i].tf) {
        int y = E[i].to;
        if (!dfn[y]) {
            Tarjan(y);
            low[x] = min(low[x], low[y]);
        }
        else if (!f[y]) {
            low[x] = min(low[x], dfn[y]);
        }
    }
    if (dfn[x] == low[x]) {
        for (f[x] = x; Stack[sum] != x; ) {
            // E[head[x]].p += E[head[Stack[sum]]].p;
            f[Stack[sum]] = x;
            sum = sum - 1;
        }
        sum = sum - 1;
    }
}
inline int Topology() {
    queue<int> q;
    memset(ans, -0x3f, sizeof(ans));
    ans[f[1]] = 0;
    for (int i = 1; i <= n; i++)
        if (!In[i]) {
            q.push(i);
        }
    for (; !q.empty(); ) {
        int now = q.front();
        q.pop();
        for (int i = head1[now]; i; i = E1[i].nxt) {
            int y = E1[i].to;
            ans[y] = max(ans[y], ans[now] + E1[i].p);
            In[y] = In[y] - 1;
            if (!In[y]) {
                q.push(y);
            }
        }
    }
    return ans[f[n]];
}
signed main() {
    for (int T = read(); T--; ) {
        n = read(), m = read();
        num = 0, sum = 0, cnt1 = 0, cnt = 0;
        memset(f, 0, sizeof(f));
        memset(ans, 0, sizeof(ans));
        memset(head, 0, sizeof(head));
        memset(head1, 0, sizeof(head1));
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(Stack, 0, sizeof(Stack));
        for (int i = 1; i <= n; i++)
            vis[i] = false;
        for (int i = 1; i <= m; i++) {
            int x = read(), y = read(), e = read(), p = read();
            Build(x, y, e, p);
            Build1(x, y, e, p);
        }
        dis[1] = 0;
        for (int i = 2; i <= n; i++)    
            dis[i] = INF;
        for (; !q.empty(); q.pop());
        for (q.push((Node) {0, 1}); !q.empty(); ) {
            Node now = q.top();
            q.pop();
            if (vis[now.y]) continue;
            vis[now.y] = true;
            for (int i = head[now.y]; i; i = E[i].nxt) { 
                if (dis[E[i].to] > dis[now.y] + E[i].e) {
                    dis[E[i].to] = dis[now.y] + E[i].e;
                    q.push((Node) {dis[E[i].to], E[i].to});
                }
            }
        }
        dis1[n] = 0, vis[n] = false;
        for (int i = 1; i < n; i++)    
            dis1[i] = INF, vis[i] = 0;
        
        for (; !q.empty(); q.pop());
        for (q.push((Node) {0, n}); !q.empty(); ) {
            Node now = q.top();
            q.pop();
            if (vis[now.y]) continue;
            vis[now.y] = true;
            for (int i = head1[now.y]; i; i = E1[i].nxt) { 
                if (dis1[E1[i].to] > dis1[now.y] + E1[i].e) {
                    dis1[E1[i].to] = dis1[now.y] + E1[i].e;
                    q.push((Node) {dis1[E1[i].to], E1[i].to});
                }
            }
        }
        // for (int i = 1; i <= n; i++)
        // //     printf("%d %d %d\n", i, dis[i], dis1[i]);
        // memset(dfn, 0, sizeof(dfn));
        for (int i = 1; i <= m; i++)
            if (dis[E[i].from] + dis1[E[i].to] + E[i].e != dis[n])
                E[i].tf = false, E[i].p = 0;
        for (int i = 1; i <= n; i++)
            if (!dfn[i])
                Tarjan(i);
        cnt1 = 0;
        memset(In, 0, sizeof(In));
        memset(head1, 0, sizeof(head1));
        for (int i = 1; i <= m; i++)
            if (f[E[i].from] != f[E[i].to] && E[i].tf) {
                Build2(f[E[i].from], f[E[i].to], E[i].p);
                In[f[E[i].to]]++;
            }
        printf("%lld %lld\n", dis[n], Topology());
        // printf("fsfs");
    }
}

WQS 二分 (未)

学习链接

ZAGER

posted @ 2019-09-25 16:13  Trimsteanima  阅读(295)  评论(1编辑  收藏  举报
Live2D