ACM算法模板整理

史诗级ACM模板整理

基本语法

字符串函数

istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );

istream& getline (istream&  is, string& str, char delim);
istream& getline (istream&  is, string& str);

char * strncpy ( char * destination, const char * source, size_t num );
	if num > source, will padding with 0. no '\0' //strlen() + 1
	
const char * strrchr ( const char * str, int character );
const char * strchr ( const char * str, int character );
	NULL if not found

const char * strstr ( const char * str1, const char * str2 );
	return the first occurance, NULL if not found

size_t strspn ( const char * str1, const char * str2 );
	The length of the initial portion of str1 containing only characters that appear in str2.
	
size_t strcspn ( const char * str1, const char * str2 );
	
const char * strpbrk ( const char * str1, const char * str2 );
	return first occurance of ch among str2
char * strtok ( char * str, const char * delimiters);

控制精度

#include<iomanip>

cout<<fixed<<setprecision(2)<<3.14159<<endl;

Black-Tec

对拍

@echo off
:loop
echo %random% | ran >in.txt
bf <in.txt > std.txt
my <in.txt > my.txt
fc std.txt my.txt > nul
if not errorlevel 1 goto loop

fread读入优化

char buf[1<<21],*p1=buf,*p2=buf;
inline int getc(){
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;	
}

pbds

hash_table
#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/hash_policy.hpp>
#include <iostream>

using namespace std;
using namespace __gnu_pbds;
gp_hash_table<int, int> h;

void judge(int i) {
	if (h.find(i) == h.end())
		cout<<"No"<<endl;
	else
		cout<<"Yes"<<h[i]<<endl;
	return;
}
int main() {
	int i;
	h[15] = 1;
	h.insert(make_pair(12, 2));
	while (cin>>i)
		judge(i);
	return 0;
}
rb_tree
#include <ext/pb_ds/assoc_container.hpp>
#include <iostream>

using namespace std;
using namespace __gnu_pbds;
tree <int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> t, b;

signed main() {
	int v = 4;
	t.insert(5);
	t.insert(2);
	t.erase(t.lower_bound(0));
	t.order_of_key(5);
	t.find_by_order(1);
	t.join(b); // no repeat
	t.split(v, b);
	return 0;
}

字符串

KMP

void getFail(string &P,int *f) {
	int i,j;
	f[0]=f[1]=0;
	for (i=1;i<m;++i) {
		j=f[i];
		while (j&&P[i]!=P[j])	j=f[j];
		f[i+1]=P[i]==P[j]?j+1:0;
	}
	return;
}
void find(string &T,string &P,int *f) {
	int i,j;
	j=0;
	for (i=0;i<n;++i) {
		while (j&&T[i]!=P[j])	j=f[j];
		if (T[i]==P[j])	j++; //!!!
		if (j==m)
			printf("%d ",i-m+2);
	}
	return;
}

exKMP

#include <iostream>
#include <string>
#include <cstring>
#include <iterator>
using namespace std;

const int maxn = 1e5 + 1;
int nxtP[maxn], Lcp[maxn];
void exKMP(const char* P, int* nxt, const char* T, int* ext) {
	int i, mx = 0, p = 0, n = strlen(T), m = strlen(P); //mx: Position where doesn't fit.
	if (nxt == ext) {
		ext[0] = n;
		p = 1; mx = 1; i = 1;
		while (mx < n && mx - i < m && T[mx] == P[mx - i])	mx++;
	} else i = 0;
	
	for (; i < n; ++i)
		if (nxt[i - p] + i < mx)	ext[i] = nxt[i - p];
		else {
			if (i >= mx)	mx = i; //i >= mx
			while (mx < n && mx - i < m && T[mx] == P[mx - i])	mx++;
			ext[i] = mx - i;
			p = i;
		}
	return;
}
signed main() {
	string T, P;
	cin>>T>>P;
	exKMP(P.data(), nxtP, P.data(), nxtP);
	exKMP(P.data(), nxtP, T.data(), Lcp);
	copy(nxtP, nxtP + P.length(), ostream_iterator <int> (cout, " "));
	cout<<endl;
	copy(Lcp, Lcp + T.length(), ostream_iterator <int> (cout, " "));
	return 0;
}

Aho-Corasick 自动机

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <map>
using namespace std;

const int maxn = 2e5 + 1, maxm = 26;
int n, ans[maxn] = { 0 };
string P[maxn], T;
struct Trie {
	int ch[maxn][maxm], sz, val[maxn];
	int ind[maxn], lazy[maxn];
	map <int, int> e;
	Trie() {
		memset(ch[0], 0, sizeof(ch[0]));
		memset(val, 0, sizeof(val));
		sz = 1; //
	}
	void insert(const char *s, int v) {
		int len = strlen(s), u = 0, c;
		for (int i = 0; i < len; ++i) {
			c = s[i] - 'a';
			if (!ch[u][c]) {
				memset(ch[sz], 0, sizeof(ch[sz]));
				val[sz] = 0; //
				ch[u][c] = sz++;
			}
			u = ch[u][c];
		}
		if (val[u])
			ans[v - 1] = -val[u];
		else
			val[u] = v;
	}
};
struct Aho_Corasick: public Trie {
	int f[maxn], last[maxn];
	void get_Fail() {
		int j, u;
		queue <int> Q;
		f[0] = 0;
		for (auto x: ch[0])
			if (x) {
				Q.push(x);
				f[x] = 0;
				last[x] = 0;
			}
		while (!Q.empty()) {
			int r = Q.front();
			Q.pop();
			for (register int c = 0; c < maxm; ++c)
				if (ch[r][c]) {
					u = ch[r][c];
					Q.push(u);
					j = f[r];
					while (j && !ch[j][c])	j = f[j];
					f[u] = ch[j][c];
					last[u] = val[f[u]] ? f[u] : last[f[u]];
					if (val[u] && last[u])
						Add(val[u], val[last[u]]);
				}
		}
	}
	
	void find(const char* T) {
		int len = strlen(T), j = 0, c;
		for (register int i = 0; i < len; ++i) {
			c = T[i] - 'a';
			while (j && !ch[j][c])	j = f[j];
			j = ch[j][c];
			if (val[j])	print(j);
			else if (last[j])	print(last[j]);
		}
		return;
	}
	
	void print(int x) {
		lazy[val[x]]++;
/* 			ans[val[x] - 1]++;
		if (last[x])
			print(last[x]); */
	}
	
	void Add(int x, int y) {
		ind[y]++;
		e.insert(make_pair(x, y));
	}
	void topocalc() {
		queue <int> Q;
		for (int x = 1; x <= n; ++x) if (!ind[x])
			Q.push(x);
		while (!Q.empty()) {
			int u, x = Q.front();	Q.pop();
			ans[x - 1] += lazy[x];
			if (e.find(x) != e.end()) {
				u = e[x];
				ind[u]--;
				lazy[u] += lazy[x];
				if (!ind[u])
					Q.push(u);
			}
		}
	}
}AC;
void read() {
	cin>>n;
	for (int i = 0; i < n; ++i) {
		cin>>P[i];
		AC.insert(P[i].data(), i + 1);
	}
	cin>>T;
}
void solve() {
	AC.get_Fail();
	AC.find(T.c_str());
	AC.topocalc();
}
void print() {
	for (int i = 0; i < n; ++i)
		if (ans[i] >= 0)
			cout<<ans[i]<<endl;
		else
			cout<<ans[-ans[i] - 1]<<endl;
}
signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	read();
	solve();
	print();
	return 0;
}

后缀数组

#include <cstdio>
#include <iostream>

using namespace std;

int sa[maxn], l1[maxn], l2[maxn];
void build_SA(int n, int m, int *s) {
	int c[maxn], *x = l1, *y = l2, p;
	memset(c, 0, sezeof(c));
	for (i = 0; i < n; ++i)	c[s[i]]++;
	for (i = 1; i < m; ++i)	c[i] += c[i - 1];
	for (i = n - 1; i >= 0; --i)	x[--c[s[i]]] = s[i];
	for (k = 1; k <= n; k <<= 1) {
		p = 0;
		for (i = 0; i < k; ++i)	y[++p] = x[i];
		for (i = 0; i < n - k; ++i)
			if (x[i] >= k)
				y[++p] = x[i] - k;
		
		memset(c, 0, sizeof(c));
		for (i = 0; i < n; ++i)	c[x[i]]++;
		for (i = 1; i < m; ++i)	c[i] += c[i - 1];
		for (i = n - 1; i >= 0; --i)	sa[--c[x[y[i]]]] = x[y[i]];
		swap(x, y);
		p = 1;
		x[sa[0]] = 0;
		for (i = 0; i < n; ++i)
			x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
		if (p >= n)	break;
		m = p;
	}
	return;
}
int main() {
	char s[255],l;
	scanf("%s", s);
	l = strlen(s);
	build_SA(l,s);
	return 0;
}

后缀自动机

#include <iostream>
#include <cstring>
#include <string>

using namespace std;

const int sigma_size = 26, maxn = 1e6 + 1;
struct SAM {
	struct Node {
		int longest, fa;
		int ch[sigma_size];
		Node() {
			memset(ch, 0, sizeof(ch));
			longest = 0;
		}
	}am[maxn << 1];
	int las = 1, cnt = 1;
	int isnp[maxn << 1];
	void insert(int c) {
		int p = las, np = ++cnt;
		las = np;
		isnp[np] = 1;
		am[np].longest = am[p].longest + 1;
		for (; p && !am[p].ch[c]; p = am[p].fa)	am[p].ch[c] = np;
		if (!p)	am[np].fa = 1;
		else {
			int q = am[p].ch[c];
			if (am[q].longest == am[p].longest + 1)	am[np].fa = q;
			else {
				int nq = ++cnt;
				am[nq] = am[q];
				am[np].fa = nq;
				am[nq].longest = am[p].longest + 1;
				am[q].fa = nq;
				for (; p && am[p].ch[c] == q; p = am[p].fa)	am[p].ch[c] = nq;
			}
		}
	}
}AM;
long long ans;
int nxt[maxn << 2], head[maxn << 2], to[maxn << 2], cnt;
void Adde(int u, int v) {
	//cout<<"Add:"<<u<<' '<<v<<endl;
	to[++cnt] = v;
	nxt[cnt] = head[u];
	head[u] = cnt;
}
int dfs(int u) {
	int x, sz = AM.isnp[u];
	for (x = head[u]; x; x = nxt[x])
		sz += dfs(to[x]);
	if (sz != 1 && 1ll * sz * AM.am[u].longest > ans)
		ans = 1ll * sz * AM.am[u].longest;
	return sz;
}
signed main() {
	int n, i;
	string s;
	cin>>s;
	n = s.length();
	for (i = 0; i < n; ++i)	AM.insert(s[i] - 'a');
	for (i = 1; i <= AM.cnt; ++i)
		Adde(AM.am[i].fa, i);
	dfs(1);
	cout<<ans<<endl;
	return 0;
}

Manacher

#include <cstdio>
#include <algorithm>

using namespace std;
const int maxn = 110001; //change this.
char s0[2 * maxn + 3],s[maxn];
int main() {
	int i,l = 0,mx = 1,len[2 * maxn + 3] = { 0 },ans = 0,p = 1;
	char ch;
	freopen("in.txt", "r", stdin);
	while ((ch = getchar())!= EOF)
		s0[l++] = ch;
	s0[l] = '\0';
	s[0] = '$';
	s[1] = '#';

	for (i = 0; i < l; ++i) {
		s[2 * (i + 1)] = s0[i];
		s[2 * i + 3] = '#';
	}
	s[2 * i + 2] = '\0';
	l = 2 * i + 1;
	for (i = 1; i < l; ++i) {
		if (i < mx)
			len[i] = min(mx - i, len[2 * p - i]); //chu zhi!!!
		else
			len[i] = 1;
		while (s[i + len[i]] == s[i - len[i]])	len[i]++;
		if (i + len[i] > mx) {
			mx = i + len[i];
			p = i;
		}
	}
	for (i = 1; i <= l; ++i)
		if (ans < len[i])
			ans = len[i];
	printf("%d\n",ans - 1);
	return 0;
}

回文自动机

#include <iostream>
#include <cstring>
#include <string>
using namespace std;

const int maxn = 5e5 + 1, sigma_size = 26;
int ans;
struct PAM {
	int ch[maxn][sigma_size], fail[maxn], last, node[maxn], len[maxn], cnt, num[maxn];
	void insert(string& s) {
		int n = s.length();
		//cout<<s<<endl;
		fail[0] = 1;
		len[1] = -1;
		cnt = 1;
		last = 0;
		node[0] = '#';
		for (int i = 1; i < n; ++i) {
			int c = (s[i] - 97 + ans) % 26 + 97 - 'a', u;
			s[i] = (char)c + 'a';
			//cout<<s[i]<<' ';
			while (s[i] != s[i - len[last] - 1])	last = fail[last]; //bu yong pd !u
			if (!ch[last][c]) {
				node[++cnt] = c;
				len[cnt] = len[last] + 2;
				u = fail[last]; //last2
				while (s[i] != s[i - len[u] - 1])	u = fail[u];
				fail[cnt] = ch[u][c]; //ch
				ch[last][c] = cnt; //sequence!
				num[ch[last][c]] = num[fail[cnt]] + 1;
			}
			last = ch[last][c];
			ans = num[last];
			cout<<ans<<' ';
		}
		return;
	}
}P;
signed main() {
	string s;
	cin>>s;
	s.insert(0, 1, '#');
	P.insert(s);
	return 0;
}

数论算法

Lucas

#include <iostream>

using namespace std;
int P,px[100001];
int qp(int x,int a) {
	int ans = 1;
	if (a == 0)
		return 1;
	while (a) {
		if (a & 1)
			ans = 1ll * ans * x % P;
		x = 1ll * x * x % P;
		a = a >> 1;
	}
	return ans;
}
int inv(int x) {
	return qp(x, P - 2);
}
int C(int n,int m) {
	if (n < m)
		return 0;
	return 1ll * px[n] * inv(px[n - m]) * inv(px[m]) % P;
}
int Lucas(int n,int m) {
	if (m == 0)
		return 1;
	return 1ll * C(n % P, m % P) * Lucas(n / P, m / P) % P;
}
int main() {
	int n,m,i,T;
	cin>>T;
	while (T--) {
		cin>>n>>m>>P;
		px[0] = 1;
		for (i = 1; i < P; ++ i)
			px[i] = 1ll * px[i-1] * i % P;
		cout<<Lucas(n + m, m)<<endl;
	}
	return 0;
}

exLucas

#include <cstdio>
#include <iostream>
#include <cmath>

using namespace std;

long long n, m;
int P;

int C(long long int n, long long int m, int p, int pk);
int fac(long long int n, int p, int pk);
int CRT(int a, int m);
int inv (int m, int p);
void exgcd(int a, int b, long long int &x, long long int &y);
int main() {
	int pk, i, p, k;
	long long ans = 0;
	cin>>n>>m>>P;
	p = P;
	k = sqrt(p + 0.5); 
	for (i = 2;i <= k; ++i)
		if (p % i == 0) {
			pk = 1;
			while (p % i == 0) {
				pk *= i;
				p /= i;
			}
			ans = (ans + 1ll * CRT(C(n, m, i, pk), P / pk)) % P; 
			
		}
	if (p != 1)
		ans = (ans + 1ll * CRT(C(n, m, p, p), P / p)) % P;
	cout<<ans<<endl;
	return 0;
}

int ksm(int x, long long int n, int p) {
	int ans = 1;
	while (n) {
		if (n & 1)
			ans = 1ll * ans * x % p;
		n >>= 1;
		x = 1ll * x * x % p;
	}
	return ans;
}
int C(long long int n, long long int m, int p, int pk) {
	long long int k = 0;
	long long int i;
	if (n < m) //Important.Habit
		return 0;
	for (i = n; i; i /= p)
		k += i / p;
	for (i = m; i; i /= p)
		k -= i / p;
	for (i = n - m; i; i /= p)
		k -= i / p;
	return 1ll * fac(n, p, pk) * inv(1ll * fac(m, p, pk) * fac(n - m, p, pk) % pk, pk) % pk * ksm(p, k, pk) % pk;
}

int fac(long long int n, int p, int pk) {
	int ans = 1;
	register int i;
	if (!n)
		return 1;
	for (i = 1; i <= pk; ++i)
		if (i % p)
			ans = 1ll * ans * i % pk;
	ans = ksm(ans, n / pk, pk);
	for (i = 1; i <= n % pk; ++i)
		if (i % p)
			ans = 1ll * ans * i % pk;
	return 1ll * ans * fac(n / p, p, pk) % pk;
}
int CRT(int a, int m) {
	return 1ll * a * m % P * inv(m, P / m) % P;
}

int inv (int m, int p) {
	long long int x, y;
	exgcd(m, p, x, y);
	return (x + p) % p;
}

void exgcd(int a, int b, long long int &x, long long int &y) {
	int t;
	if (b == 0) {
		if (a != 1)
			printf("Error.\n");
		y = 0;
		x = 1;
		return;
	}
	exgcd(b, a % b, x, y);
	t = x;
	x = y;
	y = t - a / b * y;
	return;
}

Eular函数

int euler_phi(int n) {
	int m=(int)sqrt(n+0.5);
	int ans=n;
	for (int i=2;i<=m;++i)
		if (n%i==0) {
			ans=ans/i*(i-1);
			while (n%i==0)	n/=i;
		}
	if (n>1)	ans=ans/n*(n-1);
}

int phi[maxn];
void phi_table(int n) {
	for (int i=2;i<=n;++i)	phi[i]=0;
	phi[1]=1;
	for (int i=2;i<=n;++i)
		if (!phi[i])
			for (int j=i;j<=n;j+=i) {
				if (!phi[j])
					phi[j]=j;
				phi[j]=phi[j]/i*(i-1);
			}
}

BSGS


int log_mod(int a,int b,int n) {
	int m,v,e=1,i;
	m=(int)sprt(n+0.5);
	v=inv(pow_mod(a,m,n),n);
	map <int,int>x;
	x[1]=0;
	for (i=1;i<m;++i) {
		e=mul_mod(e,a,n);
		if (!x.count(e))	x[e]=i;
	}
	for (i=0;i<m;++i) {
		if (x.count(b))	return i*m+x[b];
		b=mul_mod(b,v,n);
	}
	return -1;
}

扩展的中国剩余定理

/*When using ExCluid, mind a large prime, better use gcd and divide.*/
#include <cstdio>
#include <utility>
#include <iostream>
#define ll long long int
using namespace std;

const int maxn = 1e5 + 1;
pair <ll, ll> P;
long long tmp;
void exgcd(long long int a, long long b, long long ans) {
	if (b == 0) {
		P.first = ans / a;
		P.second = 0;
	}
	else {
		exgcd(b, a % b, ans);
		tmp = P.second;
		P.second = P.first - a / b * P.second; 
		P.first = tmp;
	}

	return;
}

ll gcd(ll a, ll b) {
	if (b == 0)
		return a;
	return gcd(b, a % b);
}

ll Gui_mul(ll x, ll n, ll mod) {
	ll ret = 0;
	int f = 1;
	if (n < 0) {
		f = -1;
		n = -n;
	}
	while (n) {
		if (n & 1)
			ret = (ret + x) % mod;
		n >>= 1;
		x = (x << 1) % mod;
	}
	return ret * f;
}
template <typename T>void gint(T& x) {
	char ch = getchar();
	x = 0;
	while (ch < '0' || ch > '9')
		ch = getchar();
	while (ch >= '0' && ch <= '9') {
		x = 10 * x + (ch ^ 48);
		ch = getchar();
	}
	return;
}
int main() {
	int n, i;
	ll m[maxn], a[maxn], lcm, t, Gcd;
	gint(n);
	for (i = 1;i <= n; ++i) {
		gint(m[i]);
		gint(a[i]);
	}
	for (i = 2;i <= n; ++i) {
		Gcd = gcd(m[i], m[i - 1]);
		lcm = m[i] / Gcd * m[i - 1];
		t = a[i] - a[i - 1];
		
		exgcd(m[i - 1], m[i], Gcd); 
		a[i] = (Gui_mul(Gui_mul(P.first, t / Gcd, m[i]), m[i - 1], lcm) + a[i - 1]) % lcm; 
		m[i] = lcm;
		if (a[i] < 0)
			a[i] = (a[i] + m[i]) % m[i];
	}
	cout<<a[n]<<endl;
	return 0;
}

高斯消元

#include <cstdio>
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;

const int maxn = 101;
typedef double Matrix[maxn][maxn];

int gauss_elimination(Matrix& A, int n) {
	int i, j, k, r;
	for (i = 0; i < n; ++i) {
		r = i;
		for (j = i + 1; j < n; ++j)
			if (fabs(A[j][i])>fabs(A[r][i]))
				r = j;
		if (r != i)
			for (j = i; j <= n; ++j)
				swap(A[r][j], A[i][j]);
		
		if (fabs(A[i][i]) < 1e-10)
			return -1;
		for (j = n; j >= i; --j)
			for (k = i + 1; k < n; ++k)
				A[k][j] -= A[k][i] / A[i][i] * A[i][j]; // -=
		
	}
	for (i = n - 1; i >= 0; --i) {
		for (j = n - 1; j > i; --j)
			A[i][n] -= A[j][n] * A[i][j];
		A[i][n] /= A[i][i];
	}
	return 0;
}
int main() {
	int n, i, j;
	Matrix A;
	cin>>n;
	for (i = 0; i < n; ++i)
		for (j = 0; j <= n; ++j)
			cin>>A[i][j];
	if (!gauss_elimination(A, n))
		for (i = 0; i < n; ++i)
			cout<<fixed<<setprecision(2)<<A[i][n]<<endl;
	else
		cout<<"No Solution"<<endl;
	return 0;
}

拉格朗日插值法

	ans = 0;
	for (i = 1; i <= n; ++i) {
		tmp = y[i]; 
		mot = 1;
		for (j = 1; j <= n; ++j)
			if (j != i) {
				tmp = tmp * (k - x[j]) % mod;
				mot = mot * (x[i] - x[j]) % mod;
			}
		ans = (ans + tmp * inv(mot)) % mod;
	}
	cout<<(ans + mod) % mod<<endl;

Mobius

	mu[1] = 1;
	for (register int i = 2; i < maxn; ++i) {
		if(!isnp[i]) {
			prime[cnt++] = i;
			mu[i] = -1;
		}
		for (register int j = 0; j < cnt && i * prime[j] < maxn; ++j) {
			isnp[i * prime[j]] = 1;
			if (i % prime[j] == 0) 
				break;
			mu[i * prime[j]] = -mu[i];
		}
	}

除法分块

#include <cstdio>
#include <iostream>
using namespace std;

int main() {
	int n, k, L, R, m;
	long long ans = 0;
	scanf("%d%d", &n, &k);
	m = min(n, k);
	for (L = 1; L <= m; L = R + 1) {
		R = min(k / (k / L), m);
		ans += (1ll * (R - L + 1) * (k % L + k % R) / 2);
	}
	if (n > k)
		ans += 1ll * k * (n - k);
	printf("%I64d\n", ans);
	return 0;
}

FFT

#include <cstdio>
#include <complex>
#include <iostream>
#include <cmath>
using namespace std;

const int maxn = 601;
const double PI = acos(-1);
int rev[maxn << 1], L;
void FFT(complex <double> *A, int len, int opt) {
	int i, j, k;
	
	complex <double> wn, w, t;
	for (i = 0; i < len; ++i)
		if (i < rev[i])
			swap(A[i], A[rev[i]]);
	for (i = 1; i < len; i <<= 1)  {
		wn = complex <double> (cos(PI / i), opt * sin(PI / i));
		for (j = 0; j < len; j += i * 2) {
			w = complex <double> (1, 0);
			for (k = 0; k < i; ++k) {
				t = w * A[j + i + k];
				A[j + k + i] = A[j + k] - t;  //
				A[j + k] = A[j + k] + t;
				w = w * wn;
			}
		}
	}
	return;
}
int main() {
	int i, len = 1, n, ans[maxn << 1] = { 0 };
	complex <double> A1[maxn << 1], A2[maxn << 1];
	char ch;
	cin>>n;
	while (len < 2 * n) {
		++L;
		len <<= 1;
	}
	for (i = 0; i < len; ++i)
		rev[i] = (rev[i >> 1] >> 1) | ((i & 1)<< (L - 1)); //
	ch = getchar();
	while (ch < '0' || ch > '9')
		ch = getchar();
	A1[n - 1] = ch ^ 48;
	for (i = n - 2; i >= 0; --i)
		A1[i] = getchar() ^ 48;
	ch = '0' - 1;
	while (ch < '0' || ch > '9')
		ch = getchar();
	A2[n - 1] = ch ^ 48;
	for (i = n - 2; i >= 0; --i)
		A2[i] = getchar() ^ 48;
	for (i = n; i < len; ++i) {
		A1[i] = 0;
		A2[i] = 0;
	}
	FFT(A1, len, 1);
	FFT(A2, len, 1);

	for (i = 0; i < len; ++i) //
		A1[i] = A1[i] * A2[i];

	FFT(A1, len, -1);
		 
	for (i = 0; i < len; ++i) {
		ans[i] += (int)(real(A1[i]) / len + 0.1);// +0.1;+=
		if (ans[i] >= 10) {
			ans[i + 1] += ans[i] / 10;
			ans[i] = ans[i] % 10;
		}
	}
	while (len > 1)
		if (ans[len - 1])
			break;
		else
			len--;
	while (len--)
		printf("%d", ans[len]);
	putchar('\n'); 
	return 0;
}

数据结构

树状数组(区间修改,区间查询)

int vdi[maxn],vd[maxn];

int lowbit(int x) {
    return x&(-x);
}
void _add(int x,int vl,int *C) {
    while (x<=N + 1) {
        C[x]=(0ll + C[x]+vl)%P;
        x+=lowbit(x);
    }
    return;
}
int _sum(int x,int *C) {
    int ret=0;
    while (x>0) {
        ret=(0ll + ret+C[x])%P; 
        x-=lowbit(x);
    }
    return ret;
}
void add(int x,int y,int vl) {
    if (x==0||y==0) {
        return;
    }
    _add(x,vl,vd); 
    _add(y+1,P -vl,vd); //-vl
    _add(x,1ll * vl*x % P,vdi);
    _add(y+1,1ll * (P - vl)*(y+1) % P,vdi);
    return;
}
int sum(int x) { //Erred.
    return (P+1ll * _sum(x,vd)*(x+1)-_sum(x,vdi))%P;
}
int ask(int x,int y) {
    return (0ll+P+sum(y)-sum(x-1))%P;
}

线段树

#include <iostream>
#include <cstdio>

using namespace std;
/* setv != -1 */
const int maxn = 500001 * 2 + 1, INF = 0x7f7f7f7f;
int minv[maxn], maxv[maxn], sumv[maxn], setv[maxn], addv[maxn];
int ql, qr, v, p, _min, _max, _sum; //A[p] = v

void query(int o, int L, int R, int add);
void pushdown(int o);
void maintain(int o, int L, int R);
void updates(int o, int L, int R); //xian set hou add;
void updatea(int o, int L, int R);
int main() {
	int n, i, opt;
	cin>>n;
	for (i = 1; i <= n; ++i) {
		cin>>v;
		ql = qr = i;
		updates(1, 1, n);
	}
	for (i = 1; i <= 5; ++i) {
		cin>>opt>>ql>>qr;
		_sum = 0;
		_min = INF;
		_max = -INF;
		switch (opt) {
		case 0: cin>>v; updates(1, 1, n); break;
		case 1: cin>>v; updatea(1, 1, n); break;
		case 2: query(1, 1, n, 0); cout<<_min<<' '<<_max<<' '<<_sum<<endl;
		}
	}
	return 0;
}

void query(int o, int L, int R, int add) { //add shang wu set
	if (setv[o] != -1) {
		_sum += (setv[o] + add + addv[o]) * (min(qr, R) - max(ql, L) + 1);
		_min = min(_min, setv[o] + add + addv[o]);
		_max = max(_max, setv[o] + add + addv[o]);
	}
	else
		if (ql <= L && qr >= R) {
			_sum += sumv[o] + add * (R - L + 1);
			_min = min(_min, minv[o] + add);
			_max = max(_max, maxv[o] + add);
		}
		else {
			int lc = 2 * o, rc = 2 * o + 1, M = L + (R - L) / 2;
			if (ql <= M)
				query(lc, L, M, add + addv[o]);
			if (qr > M)
				query(rc, M + 1, R, add + addv[o]);
		}
	return;
}
void updates(int o, int L, int R) { //set qian wu add, set shang ke you add.
	if (L >= ql && qr >= R) {
		setv[o] = v;
		addv[o] = 0;
	}
	else {
		int lc = 2 * o, rc = 2 * o + 1, M = L + (R - L) / 2;
		pushdown(o);
		if (ql <= M)
			updates(lc, L, M);
		else
			maintain(lc, L, M);
		if (qr > M)
			updates(rc, M + 1, R);
		else
			maintain(rc, M + 1, R);
	}
	maintain(o, L, R);
	return;
}
void updatea(int o, int L, int R) {
	if (L >= ql && qr >= R)
		addv[o] += v;
	else {
		int lc = 2 * o, rc = 2 * o + 1, M = L + (R - L) / 2;
		pushdown(o);
		if (ql <= M)
			updatea(lc, L, M);
		else
			maintain(lc, L, M);
		if (qr > M)
			updatea(rc, M + 1, R);
		else
			maintain(rc, M + 1, R);
	}
	maintain(o, L, R);
	return;
}

void pushdown(int o) {
	int lc = 2 * o, rc = 2 * o + 1;
	if (setv[o] == -1) {
		addv[lc] += addv[o];
		addv[rc] += addv[o];
	}
	else {
		setv[lc] = setv[rc] = setv[o] + addv[o];
		addv[lc] = 0; addv[rc] = 0;
	}
	addv[o] = 0;
	setv[o] = -1;
}

void maintain(int o, int L, int R) {
	int lc = 2 * o, rc = 2 * o + 1;
	if (setv[o] != -1) {
		sumv[o] = setv[o] * (R - L + 1);
		minv[o] = setv[o];
		maxv[o] = setv[o];
	}
	else
		if (L < R) {
			sumv[o] = sumv[lc] + sumv[rc];
			minv[o] = min(minv[lc], minv[rc]);
			maxv[o] = max(maxv[lc], maxv[rc]);
		}
	sumv[o] += addv[o] * (R - L + 1);
	minv[o] += addv[o];
	maxv[o] += addv[o];
	return;
}

主席树

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 2e5 + 1;
int a[maxn], b[maxn], tot, p, v;
int cnt, C[maxn << 5], rt[maxn], lc[maxn << 5], rc[maxn << 5];
int build(int L, int R) {
	int mid = L + (R - L) / 2, u = cnt++;
	if (L == R)	{
		C[u] = 0;
		return u;
	}
	lc[u] = build(L, mid);
	rc[u] = build(mid + 1, R);
	return u;
}
int update(int o, int L = 1, int R = tot) {
	int mid = L + (R - L) / 2, u = cnt++;
	if (L == R)	{
		C[u] = C[o] + v;
		return u;
	};
	lc[u] = lc[o];	rc[u] = rc[o];
	if (p <= mid)	lc[u] = update(lc[u], L, mid);
	else	rc[u] = update(rc[u], mid + 1, R);
	C[u] = C[lc[u]] + C[rc[u]];
	
	return u;
}
int query(int o1, int o2, int k, int L = 1, int R = tot) {
	int mid = L + (R - L) / 2;
	if (L == R)	return mid;
	if (k <= C[lc[o2]] - C[lc[o1]])	return query(lc[o1], lc[o2], k, L, mid); 
	else	return query(rc[o1], rc[o2], k - (C[lc[o2]] - C[lc[o1]]), mid + 1, R);
}

signed main() {
	int n, m, i, l, r, k;
	freopen("testdata.in", "r", stdin);
	freopen("my.out", "w", stdout);
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for (i = 0; i < n; ++i) {
		cin>>a[i];
		b[i] = a[i];
	}
	sort(b, b + n);
	tot = unique(b, b + n) - b;
	rt[0] = build(1, tot);
	v = 1;
	for (i = 0; i < n; ++i) {
		p = lower_bound(b, b + tot, a[i]) - b + 1;
		rt[i + 1] = update(rt[i]);
	}
	while (m--) {
		cin>>l>>r>>k;
		cout<<b[query(rt[l - 1], rt[r], k) - 1]<<endl;
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

Treap

#include <iostream>
#include <cstdlib>
using namespace std;

const int maxn = 1e5 + 1, INF = 0x7f7f7f7f;
int size[maxn], v[maxn], fix[maxn], son[maxn][2], num[maxn], cnt, R;

void pushup(int p) {
	size[p] = size[son[p][0]] + size[son[p][1]] + num[p];
	return;
}
void rotate(int &p, int dir) {
	int t = son[p][dir];
	son[p][dir] = son[t][dir ^ 1];
	son[t][dir ^ 1] = p;
	p = t;
	pushup(son[p][0]);
	pushup(son[p][1]);
	return;
}
void ins(int &p, int x) {
	if (!p) {
		p = ++cnt;
		v[p] = x;
		num[p] = 1;
		size[p] = 1;
		fix[p] = rand();
		return;
	}
	if (v[p] == x) {
		num[p]++;
		size[p]++;
		return;
	}
	int d = (x > v[p]);
	ins(son[p][d], x);
	if ((fix[p] < fix[son[p][d]]) != d)
		rotate(p, d);
	pushup(p);
}
void del(int &p, int x) {
	if (!p) {
		cout<<"Not exist."<<endl;
		return;
	}
	if (v[p] > x)
		del(son[p][0], x);
	if (v[p] < x)
		del(son[p][1], x);
	if (v[p] == x) {
		if (!son[p][0] && !son[p][1]) {
			num[p]--;
			if (num[p] == 0)
				p = 0;
		}
		else if (!son[p][0] && son[p][1]) {
			rotate(p, 1);
			del(son[p][0], x);
		}
		else if (son[p][0] && !son[p][1]) {
			rotate(p, 0);
			del(son[p][1], x);
		}
		else if (num[p] > 1)
			num[p]--;
		else {
			int d = (fix[son[p][0]] < fix[son[p][1]]);
			rotate(p, d);
			del(son[p][d ^ 1], x);
		}
	}
	pushup(p);
	return;
}
int getrank(int p, int x) {
	if (!p)
		return 0;
	if (v[p] == x)
		return size[son[p][0]] + 1;
	if (v[p] > x)
		return getrank(son[p][0], x);
	else
		return size[son[p][0]] + num[p] + getrank(son[p][1], x);
}
int getnum(int p, int r) {
	int left = size[son[p][0]];
	if (!p)
		return -1;
	if (left >= r)
		return getnum(son[p][0], r);
	if (left < r && left + num[p] >= r)
		return v[p];
	else
		return getnum(son[p][1], r - left - num[p]);
}
int getpre(int p, int x) {
	if (!p)
		return -INF;
	if (v[p] >= x)
		return getpre(son[p][0], x);
	else
		return max(v[p], getpre(son[p][1], x));
}
int getsuf(int p, int x) {
	if (!p)
		return INF;
	if (v[p] <= x)
		return getsuf(son[p][1], x);
	else
		return min(v[p], getsuf(son[p][0], x));	
}
int main() {
	int n, opt, x;
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);cout.tie(nullptr);
	cin>>n;
	while (n--) {
		cin>>opt>>x;
		switch (opt) {
			case 1:ins(R, x);break;
			case 2:del(R, x);break;
			case 3:cout<<getrank(R, x)<<endl;break;
			case 4:cout<<getnum(R, x)<<endl;break;
			case 5:cout<<getpre(R, x)<<endl;break;
			case 6:cout<<getsuf(R, x)<<endl;break;
		}
	}
	return 0;
}

Splay

#include <iostream>
#include <iterator>
#include <algorithm>
#include <cstdlib>
using namespace std;

const int maxn = 1e5 + 5;
int n;
int ch[maxn][2], fa[maxn], size[maxn], num[maxn], cnt, R, v[maxn], rev[maxn];
void pushdown(int x) {
	if (rev[x]) {
		swap(ch[x][0], ch[x][1]);
		rev[ch[x][0]] ^= 1;
		rev[ch[x][1]] ^= 1;
		rev[x] = 0;
	}
}
void pushup(int x) {
	size[x] = num[x] + size[ch[x][0]] + size[ch[x][1]];
}
int kth(int k) {
	int cur = R;
	if (k > cnt)
		cout<<"Err"<<endl;
	while (1) {
		pushdown(cur); 
		if (ch[cur][0] && k <= size[ch[cur][0]])
			cur = ch[cur][0];
		else if (k > size[ch[cur][0]] + num[cur]) {
			k -= (size[ch[cur][0]] + num[cur]);
			cur = ch[cur][1];
		}
		else
			return cur;
	}
}

void output(int x) {
	pushdown(x);
	if (ch[x][0])	output(ch[x][0]);
	if (num[x] != 0 && v[x] <= n && v[x] >= 1)
		for (int i = 1; i <= num[x]; ++i)
			cout<<v[x]<<' ';
	if (ch[x][1])	output(ch[x][1]);
}
void rotate(int x) {
	int d = (ch[fa[x]][1] == x), p = fa[x];
	pushdown(p);
	pushdown(x);
	fa[x] = fa[p];
	if (fa[p]) 
		ch[fa[p]][ch[fa[p]][1] == p] = x;
	ch[p][d] = ch[x][d ^ 1];
	if (ch[x][d ^ 1]) 
		fa[ch[x][d ^ 1]] = p;
	ch[x][d ^ 1] = p;
	fa[p] = x;
	
	pushup(x);
	pushup(p);
	return;
}

void splay(int x, int goal = 0) {
	while (fa[x] != goal) {
		int y = fa[x], z = fa[y];
		pushdown(z);
		pushdown(y); 
		if (z != goal) {
			if ((ch[fa[x]][1] == x) == (ch[fa[y]][1] == y))
				rotate(y);
			else
				rotate(x);
		}
		rotate(x);
 
	}
	if (!goal)
		R = x;
}

void insert(int val) {
	int cur = R, p = fa[cur];
	while (cur && v[cur] != val) {
		p = cur;
		cur = ch[cur][val > v[cur]];
	}
	if (cur) {
		num[cur]++;
		size[cur++];
	}
	else {
		cur = ++cnt;
		if (p)
			ch[p][val > v[p]] = cur; 
		v[cur] = val;
		fa[cur] = p;
		num[cur] = size[cur] = 1;
	}
	splay(cur);
}
void find(int val) {
	if (!R)
		return;
	int cur = R;
	while (v[cur] != val && ch[cur][v[cur] < val])
		cur = ch[cur][v[cur] < val]; //
	splay(cur);
}
void reverse(int l, int r) {
	int x =	kth(l - 1), y = kth(r + 1);

	splay(x);
	splay(y, x);
	rev[ch[y][0]] ^= 1;
}
int pre(int val) {
	find(val);
	if (v[R] < val)
		return R;
	int cur = ch[R][0];
	while (ch[cur][1]) //
		cur = ch[cur][1];
	return cur;
}
int suc(int val) {
	find(val);
	if (v[R] > val)
		return R;
	int cur = ch[R][1];
	while (ch[cur][0])
		cur = ch[cur][0];
	return cur;
}
void remove(int val) {
	int nxt = suc(val), lst = pre(val);
	splay(lst);
	splay(nxt, lst);
	int del = ch[lst][0];
	if (num[del] > 1) {
		num[del]--;
		rotate(del);
	}
	else {
		ch[nxt][0] = 0;
		rotate(nxt);
	}
	return;
}
int buildtree(int x, int y, int fat) {
	int mid = x + (y - x) / 2;
	if (x < mid) {
		ch[mid + 1][0] = buildtree(x, mid - 1, mid + 1);
		size[mid + 1] += size[ch[mid + 1][0]];
	}
	size[mid + 1] += 1; 
	num[mid + 1] = 1;
	v[mid + 1] = mid;
	fa[mid + 1] = fat;
	if (mid < y) {
		ch[mid + 1][1] = buildtree(mid + 1, y, mid + 1);
		size[mid + 1] += size[ch[mid + 1][1]];
	}
	return mid + 1;
}
int main() {
	int m, x, y;
	ios_base::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	R = buildtree(0, n + 1, 0);
	cnt = n + 2;
	while (m--) {
		cin>>x>>y;
		reverse(x + 1, y + 1);
	}
	output(R);
	return 0;
}

图论

Dijkstra

#include <cstdio>
#include <iostream>
#include <queue>

using namespace std;
const int maxn=100001,INF=1e9;
struct Edge {
	int from,to,dist;
	Edge(int u,int v,int d):
		from(u),
		to(v),
		dist(d){}
};
struct Dijkstra {
	int n;
	vector <Edge> edges;
	vector <int> G[maxn];
	int d[maxn];
	
	Dijkstra(int n1) {
		n=n1;
		for (int i=1;i<=n;++i)
			d[i]=INF;
		edges.clear();
		for (int i=1;i<=n;++i)
			G[i].clear();
		return;
	}
	void AddEdge(int u,int v,int dist) {
		edges.push_back((Edge) (u,v,dist));
		G[u].push_back(edges.size()-1);
		return;
	}
	struct HeapNode{
		int u,d;
		void HeapNode(int m,int k):
			u(m),
			d(k) {}
		bool operator <(const HeapNode& rhs) const {
			return d<rhs.d;
		}
	};
	void dijkstra(int S) {
		priority_queue <HeapNode> Q;
		d[S]=0;
		Q.push((HeapNode) (S,0));
		while (!Q.empty()) {
			HeapNode x=Q.top();Q.pop();
			if (x.d!=d[u])	continue;
			int u=x.u,sz=G[u].size();
			for (int j=0;j!=sz;++j) {
				Edge& e=edges[G[u][j]];
				if (d[e.to]>d[u]+e.dist) {
					d[e.to]=d[u]+e.dist;
					Q.push(HeapNode (e.to,d[e.to]));
				}
			}
		}
		return;
	}
};
int main() {
	int N,M,S,u,v,w;
	cin>>N>>M>>S;
	Dijkstra D(N);
	for (int i=1;i<=M;++i) {
		cin>>u>>v>>w;
		D.AddEdge(u,v,w);
	}
	D.dijkstra(S);
	for (int i=1;i<=N;++i)
		cout<<D.d[i]<<' ';
	return 0;
}

Bellman-Ford

const int maxn=100,maxm=1000;
void Bellman-Ford(int n,int m,int S) {
	int w[maxn],u[maxn],v[maxn],i,j;
	for (i=1;i<=m;++i)
		cin>>w[i]>>u[i]>>v[i];
	for (k=1;k<n;++k)
		for (i=1;i<=m;++i) {
			int x=u[i],y=v[i];
			if (d[x]<INF)
				d[y]=min(d[y],d[x]+w[i]);
		}
}

Floyd

LCA

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=500001,maxm=maxn*2;
int neext[maxm],to[maxm],head[maxn],cnt,
	p[maxn][21],deep[maxn],lg[21];
void add(int x,int y) {
	to[++cnt]=y;
	neext[cnt]=head[x];
	head[x]=cnt;
	return;
}
int LCA(int x,int y) {
	int i;
	if (deep[x]<deep[y])	swap(x,y);
	while (deep[x]>deep[y])
	    x=p[x][lg[deep[x]-deep[y]]-1];
	if (x==y)   return x;
	for (i=lg[deep[x]]-1;i>=0;--i) 
		if (p[x][i]!=p[y][i]) {
			x=p[x][i];
			y=p[y][i];
		}
	if (p[x][0]==p[y][0])	return p[x][0];
	return -1;
}
void dfs(int n,int d) {
	for (int i=head[n];i;i=neext[i]) {
		int x=to[i];
		if (!deep[x]) {
		    deep[x]=d+i; //tiao zheng shun xu,hou dfs.
			p[x][0]=n;
			dfs(x,d+1);
		}
	}
	return;
}
int main() {
	int N,M,S,x,y,i,j;
	scanf("%d%d%d",&N,&M,&S);
	for (i=1;i<=N;++i)
	    lg[i]=lg[i-1]+(1<<lg[i-1]==i); //
	for (i=1;i<N;++i) {
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	p[S][0]=S;
	deep[S]=1;
	dfs(S,0);
	for (j=1;j<=20;++j)
		for (i=1;i<=N;++i)
			p[i][j]=p[p[i][j-1]][j-1];
	printf("aa%daa",p[5][0]);
	for (i=1;i<=M;++i) {
		scanf("%d%d",&x,&y);
		printf("%d\n",LCA(x,y));
	}
	return 0;
}

树链剖分

//BIT when * yao qu moooooooooooooooooo * 6 months.
#include <cstdio>
#include <cassert>
using namespace std;
const int maxn=(int)1e5+1;
int N,R,P;
int nxt[maxn*2],to[maxn*2],head[maxn],cnt;
int size[maxn],fa[maxn],id[maxn],cntid,deep[maxn],son[maxn],rank[maxn],top[maxn];
int vdi[maxn],vd[maxn];
int Rint(int &x) {
    char ch=getchar();
    x=0;
    while (ch<'0'||ch>'9')
        ch=getchar();
    while (ch>='0'&&ch<='9') {
        x=x*10+(ch^48);
        ch=getchar();
    }
    return x;
}
int lowbit(int x) {
    return x&(-x);
}
void _add(int x,int vl,int *C) {
    while (x<=N + 1) {
        C[x]=(0ll + C[x]+vl)%P;
        x+=lowbit(x);
    }
    return;
}
int _sum(int x,int *C) {
    int ret=0;
    while (x>0) {
        ret=(0ll + ret+C[x])%P; 
        x-=lowbit(x);
    }
    return ret;
}
void add(int x,int y,int vl) {
    if (x==0||y==0) {
        return;
    }
    _add(x,vl,vd); 
    _add(y+1,P -vl,vd); //-vl
    _add(x,1ll * vl*x % P,vdi);
    _add(y+1,1ll * (P - vl)*(y+1) % P,vdi);
    return;
}
int sum(int x) { //Erred.
    return (P+1ll * _sum(x,vd)*(x+1)-_sum(x,vdi))%P;
}
int ask(int x,int y) {
    return (0ll+P+sum(y)-sum(x-1))%P;
}
void Adde(int u,int v) {
    to[++cnt]=v;
    nxt[cnt]=head[u];
    head[u]=cnt;
    return;
}
void dfs1(int x) {
    int i,t;
    size[x]=1;//woc
    deep[x]=deep[fa[x]]+1;
    
    for (i=head[x];i;i=nxt[i]) {
        t=to[i];
        if (t!=fa[x]) {
            fa[t]=x;
            dfs1(t);
            size[x]+=size[t];
            if (size[son[x]]<size[t]) //kuo hao.
                son[x]=t;
        }
    }
    return;
}
void dfs2(int x,int t) {
    int i,tto;
    id[x]=++cntid;
    rank[cntid]=x;
    top[x]=t;
    if (!son[x])
        return;
    dfs2(son[x],t);
    for (i=head[x];i;i=nxt[i]) {
        tto=to[i];
        if (tto!=fa[x]&&tto!=son[x])
            dfs2(tto,tto);
    }
    return;
}
void addpath(int x,int y,int vl) {
    while (top[x]!=top[y])
        if (deep[top[x]]>deep[top[y]]) {
            add(id[top[x]],id[x],vl);
            x=fa[top[x]];
        }
        else {
            add(id[top[y]],id[y],vl);
            y=fa[top[y]];
        }
    if (id[x]<=id[y]) //same Hchain.
        add(id[x],id[y],vl);
    else
        add(id[y],id[x],vl);
    return;
}
int askpath(int x,int y) {
    long long ret=0;
    while (top[x]!=top[y]) {
        if (deep[top[x]]>deep[top[y]]) {
            ret+=ask(id[top[x]],id[x]);
            x=fa[top[x]];
        }
        else {
            ret+=ask(id[top[y]],id[y]);
            y=fa[top[y]];
        }
        ret%=P;
    }
    if (deep[x]>deep[y])
        ret+=ask(id[y],id[x]);
    else
        ret+=ask(id[x],id[y]);
    return (int)(ret%P);
}

signed main() {
    int i,M,u,v,op,x,y,z,v0[maxn];
	//freopen("testdata.in", "r", stdin);
	//freopen("my.out", "w", stdout);
    Rint(N);Rint(M);Rint(R);Rint(P);
    for (i=1;i<=N;++i) {
        Rint(v0[i]);
    }
    for (i=1;i<N;++i) {
        Rint(u);Rint(v);
        Adde(u,v);
        Adde(v,u);
    }
    dfs1(R);
    dfs2(R,R);
    for (i=1;i<=N;++i)
        add(id[i],id[i],v0[i]);
    while (M--) {
        Rint(op);
        switch (op) {
            case 1:
                Rint(x);Rint(y);Rint(z);
                addpath(x,y,(0ll+P + z)%P); //
                break;
            case 2:
                Rint(x);Rint(y);
                printf("%d\n",askpath(x,y));
				break;
            case 3:
                Rint(x);Rint(z);
                add(id[x],id[x]+size[x]-1,(0ll+P + z)%P);//
                break;
            case 4:
                Rint(x);
                printf("%d\n",ask(id[x],id[x]+size[x]-1));
        }
    }
	//fclose(stdin);
	//fclose(stdout);
    return 0;
}

树上点分治

#include <iostream>
using namespace std;

const int maxn = 2e4 + 1;
int nxt[maxn << 1], head[maxn], to[maxn << 1], w[maxn << 1], ecnt;
int ans, rt, d[3], mnsz, sz[maxn], vis[maxn], tot;

int vv[maxn];
void AddE(int u, int v, int le) {
	to[++ecnt] = v;
	w[ecnt] = le;
	nxt[ecnt] = head[u];
	head[u] = ecnt;
	return;
}
int getroot(int u, int fa) {
	static int cnt = 0;
	cnt++;
	if (vv[u])
		cout<<"Visited! @"<<u<<", fa = "<<fa<<endl;
	vv[u] = 1;
	int mx = 0;
	sz[u] = 1;
	for (int i = head[u]; i; i = nxt[i]) {
		int v = to[i];
		if (vis[v] || v == fa)
			continue;
		sz[u] += getroot(v, u);
		mx = max(mx, sz[v]);
	}
	mx = max(mx, tot - sz[u]);
	if (mx < mnsz) {
		rt = u;
		mnsz = mx;
	}
	cnt--;
	vv[u] = 0;
	return sz[u];
}
void getd(int u, int fa, int dis) {
	d[dis % 3]++;
	for (int i = head[u]; i; i = nxt[i]) {
		int v = to[i];
		if (vis[v] || v == fa)	continue;
		getd(v, u, (dis + w[i]) % 3);
	}
}
int getans(int u, int dis) {
	d[0] = d[1] = d[2] = 0;
	getd(u, -1, dis);
	return d[0] * d[0] + d[1] * d[2] * 2;
}
void solve(int u) {
	vis[u] = 1;
	ans += getans(u, 0);
	for (int x = head[u]; x; x = nxt[x]) {
		int v = to[x];
		if (vis[v])
			continue;
		ans -= getans(v, w[x]);
		mnsz = tot = sz[v];	rt = 0;	getroot(v, -1);
		solve(rt);
	}
	return;
}
int gcd(int a, int b) {
	if (b == 0)
		return a;
	return gcd(b, a % b);
}
int vid[maxn], id[maxn], cc;
void test(int u, int fa) {
	if (vid[u] == 1) {
		cout<<"Err "<<cc<<endl;
		for (int i = 1; i <= cc; ++i)
			cout<<id[i]<<' ';
		return;
	}
	vid[u] = 1;
	id[++cc] = u;
	for (int i = head[u]; i; i = nxt[i]) {
		int v = to[i];
		if (v != fa)
			test(v, u);
	}
	return;
}
signed main() {
	int n, u, v, i, t, ww;
#ifndef ONLINE_JUDGE
freopen("testdata.in", "r", stdin);
#endif
	cin>>n;
	for (i = 0; i < n - 1; ++i) {
		cin>>u>>v>>ww;
		ww = ww % 3;
		AddE(u, v, ww);	AddE(v, u, ww);
	}
	test(1, -1);
	mnsz = tot = n;	getroot(1, -1);
	t = gcd(ans, n * n);
	cout<<ans / t<<'/'<<n * n / t<<endl;
	return 0;
}

CV-BCC 无向图的双连通分量

#include <iostream>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;

const int maxn = 2e4 + 1;
int dfs_clock, pre[maxn], iscut[maxn], bccno[maxn], bcc_count;
struct Edge {
	int u, v;
};
vector <int> bcc[maxn], G[maxn];
stack <Edge> S;
void AddE(int u, int v) {
	G[u].push_back(v);
}
int tarjan(int u, int fa) {
	int lowu = pre[u] = ++dfs_clock, child = 0;
	for (auto v: G[u]) {
		if (!pre[v]) {
			child++;
			S.push((Edge) {u, v});
			int lowv = tarjan(v, u);
			lowu = min(lowu, lowv);
			if (lowv >= pre[u]) {
				iscut[u] = 1;
				++bcc_count;
				bcc[bcc_count].clear();
				//cout<<dfs_clock<<' '<<u<<'>'<<v<<','<<lowv<<'|'<<bcc_count<<endl;
				while (1) {
					Edge e = S.top();	S.pop();
					if (bccno[e.u] != bcc_count) {
						bcc[bcc_count].push_back(e.u);
						bccno[e.u] = bcc_count;
					}
					if (bccno[e.v] != bcc_count) {
						bcc[bcc_count].push_back(e.v);
						bccno[e.v] = bcc_count;
					}
					if (e.u == u && e.v == v)	break;
				}
			}
		} else if (pre[v] < pre[u] && v != fa) {
			S.push((Edge) {u, v});
			lowu = min(lowu, pre[v]); //Err
		}
	}
	if (fa == -1 && child == 1)	iscut[u] = 0; //Err
	return lowu;
}
signed main() {
	int n, m, u, v, i;
	cin>>n>>m;
	while (m--) {
		cin>>u>>v;
		AddE(u, v);
		AddE(v, u);
	}
	for (i = 1; i <= n; ++i)
		if (!pre[i])
			tarjan(i, -1);
	cout<<count(iscut + 1, iscut + n + 1, 1)<<endl;
	for (i = 1; i <= n; ++i)
		if (iscut[i])
			cout<<i<<' ';
	return 0;
}

SCC 有向图的强连通分量

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

const int maxn = 1e4 + 1;
int n;
int pre[maxn], dfs_clock, sccno[maxn], scc_count;
int c[maxn], topo[maxn];
vector <int> G[maxn], GA[maxn], scc[maxn];
stack <int> S;
void AddE(int u, int v) {
	G[u].push_back(v);
}
void AddED(int u, int v) {
	//cout<<"Add"<<u<<' '<<v<<endl;
	GA[u].push_back(v);
}
int tarjan(int u) {
	int lowlinku = pre[u] = ++dfs_clock;
	S.push(u);
	for (auto x: G[u])
		if (!pre[x]) {
			int lowlinkv = tarjan(x);
			lowlinku = min(lowlinku, lowlinkv);
		} else if (!sccno[x])
			lowlinku = min(lowlinku, pre[x]);
	if (lowlinku == pre[u]) {
		++scc_count;
		scc[scc_count].clear();
		//cout<<endl<<scc_count<<":";
		while (1) {
			int v = S.top(); S.pop();
			scc[scc_count].push_back(v);
			sccno[v] = scc_count;
			//cout<<v<<' ';
			if (v == u)	break;
		}
	}
	return lowlinku;
}
int dfs(int u) {
	static int cnt = scc_count;
	if (c[u] == -1)
		return false;
	c[u] = -1;
	for (auto v: GA[u])
		if (!c[v] && !dfs(v))	return false;
	c[u] = 1;
	topo[cnt--] = u;
	return true;
}
int toposort(int n) {
	for (int i = 1; i <= n; ++i)
		if (!c[i])
			if (!dfs(i))
				return false;
	return true;
}

signed main() {
	int m, i, u, v;
	cin>>n>>m;
	while (m--) {
		cin>>u>>v;
		AddE(u, v);
	}
	for (i = 1; i <= n; ++i) {
		if (!pre[i])
			tarjan(i);
	}
	for (i = 1; i <= n; ++i) //Err Impppp
		for (int v: G[i]) if (sccno[i] != sccno[v]) //Err2.
			AddED(sccno[i], sccno[v]);
	if (!toposort(scc_count))
		cout<<"Shit!"<<endl;
	return 0;
}

网络流

Edmonds-Karp

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

using namespace std;
const int infinity=1e9,maxn=1e4+1;
struct EdmondsKarp {
    struct Edge {
        int from,to,cap,flow;
        Edge(int u,int v,int c,int f):
            from(u),to(v),cap(c),flow(f){}
    };
    
    int n,m,aug[maxn],p[maxn];
    vector <int> G[maxn];
    vector <Edge> edges;
    
    EdmondsKarp(int n) {
        for (int i=0;i<=n;++i)	G[i].clear();
        edges.clear();
    }
    
    void AddEdge(int u,int v,int cap) {
        edges.push_back(Edge(u,v,cap,0));
        edges.push_back(Edge(v,u,0,0));
        m=edges.size();
        G[u].push_back(m-2);
        G[v].push_back(m-1);
        return;
    }
    
    int MaxFlow(int S,int T) {
        int flow=0;
        while (1) {
            memset(aug,0,sizeof(aug));
            queue <int> Q;
            Q.push(S);
            aug[S]=infinity;
            p[S]=-1;
            while (!Q.empty()) {
                int x=Q.front();
                Q.pop();
                for (int j=0;j<G[x].size();++j) {
                    Edge &e=edges[G[x][j]];
                    if (!aug[e.to]&&e.cap>e.flow) {
                        p[e.to]=G[x][j];
                        aug[e.to]=min(aug[x],e.cap-e.flow);
                        Q.push(e.to); 
                    }
                }
                if (aug[T])	break;
            }
            if (!aug[T])	break;
            for (int u=T;u!=S;u=edges[p[u]].from) {
                edges[p[u]].flow+=aug[T];
                edges[p[u]^1].flow-=aug[T]; 
            }
            
            flow+=aug[T];
        }
        return flow;
    }
};
int main() {
    int N,M,S,T,u,v,f;
    cin>>N>>M>>S>>T;
    EdmondsKarp E(N);
    for (int i=1;i<=M;++i) {
        cin>>u>>v>>f;
        E.AddEdge(u,v,f);
    }
    cout<<E.MaxFlow(S,T)<<endl;
    return 0;
}

MinCostMaxFlow

#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#define maxn 5001
#define INF 0x7f7f7f7f
using namespace std;
struct MCMF {
	int flow,cost,m;
	MCMF ():
		flow(0),
		cost(0){
			E.clear();
		}
	
	struct Edges {
		int to,flow,cost,cap;
	};
	vector <Edges> E;
	vector <int> G[maxn];
	void Adde(int u,int v,int w,int f) {
		E.push_back(Edges {v,0,f,w});
		E.push_back(Edges {u,0,-f,0});
		m=E.size();
		G[u].push_back(m-2);
		G[v].push_back(m-1);
		return;
	}
	void CALC(int S,int T) {
		while (M(S,T));
		return;
	}
	int M(int S,int T) {
		int i,a[maxn],p[maxn],inq[maxn],d[maxn];
		queue <int> Q;
		memset(a,0,sizeof(a));
		memset(p,0,sizeof(p));
		memset(inq,0,sizeof(inq));
		memset(d,0x7f,sizeof(d));
		inq[S]=1;
		a[S]=INF;
		d[S]=0;
		Q.push(S);
		while (!Q.empty()) {
			int i,x=Q.front();Q.pop();
			inq[x]=0;
			for (i=0;i<(int)G[x].size();++i) {
				Edges &e=E[G[x][i]];
				if (e.cap>e.flow&&d[e.to]>d[x]+e.cost) {
					d[e.to]=d[x]+e.cost;
					a[e.to]=min(a[x],e.cap-e.flow);
					p[e.to]=G[x][i];
					if (!inq[e.to]) {
						Q.push(e.to);
						inq[e.to]=1;
					}
				}
			}
		}
		if (d[T]==INF)	return false;
		flow+=a[T];
		cost+=a[T]*d[T];
		for (i=T;i!=S;i=E[p[i]^1].to) { //!!!!!!!
			E[p[i]].flow+=a[T];
			E[p[i]^1].flow-=a[T];
		}
		return true;
	}
};
int main() {
	int N,M,S,T;
	int u,v,w,f,i;
	MCMF A;
	scanf("%d%d%d%d",&N,&M,&S,&T);
	for (i=1;i<=M;++i) {
		scanf("%d%d%d%d",&u,&v,&w,&f);
		A.Adde(u,v,w,f);
	}
	A.CALC(S,T);
	printf("%d %d\n",A.flow,A.cost);
	return 0;
}

其他基本操作

手写快排

void qs(int *a,int x,int y) {
	int i=x,j=y,mid=a[x+(y-x)/2];
	while (i<=j) {
		while (a[i]<mid)	i++;
		while (a[j]>mid)	j--;
		if (i<=j)
		    swap(a[i++],a[j--]);
	}
	if (i<y)	qs(a,i,y);
	if (x<j)	qs(a,x,j);
	return;
}

CDQ分治

//3D seq
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn = 1e5 + 1, maxk = 2e5 + 1;
int n, k;
int v[maxn], x[maxn], y[maxn], z[maxn], num[maxn], t[maxn], tot, p[maxn], ans[maxn];
int val[maxk];
int cmp(int i, int j) {
	return x[i] < x[j] || (x[i] == x[j] && ((y[i] < y[j]) || (y[i] == y[j] && z[i] < z[j])));
}
void read() {
	int i, j;
	cin>>n>>k;
	for (i = 0; i < n; ++i) {
		cin>>x[i]>>y[i]>>z[i];
		p[i] = i;
	}
	sort(p, p + n, cmp);
	for (i = 0; i < n; i = j) {
	    int t = p[i];
		p[tot++] = t;
		j = i + 1;
		while (j < n && !((x[p[i]] ^ x[p[j]]) || (y[p[i]] ^ y[p[j]]) || (z[p[i]] ^ z[p[j]]))) {
			v[t]++;
			j++;
		}
		v[t]++;
	}
}

int lowbit(int x) {
	return x & (-x);
}
void add(int pos, int vl) {
	while (pos <= k) {
		val[pos] += vl;
		pos += lowbit(pos);
	}
}
int sum(int pos) {
	int ret = 0;
	while (pos) {
		ret += val[pos];
		pos -= lowbit(pos);
	}
	return ret;
}

void CDQ(int L, int R) {
	int mid = L + (R - L) / 2, i = L, j = mid + 1, cnt = L;
	if (L == R)	return;
	CDQ(L, mid);CDQ(mid + 1, R);
	while (i <= mid || j <= R) {
		if (j > R || (i <= mid && y[p[i]] <= y[p[j]])) {
			add(z[p[i]], v[p[i]]);
			t[cnt++] = p[i++];
		}
		else {
			ans[p[j]] += sum(z[p[j]]);
			t[cnt++] = p[j++];
		}
	}

	for (i = L; i <= mid; ++i)
		add(z[p[i]], -v[p[i]]);
	for (i = L; i <= R; ++i)
		p[i] = t[i];
	return;
}
void solve() {
	CDQ(0, tot - 1);

}
void print() {
	int i;
	int num[maxn] = { 0 };
	for (i = 0; i < tot; ++i)
		num[ans[p[i]] + v[p[i]] - 1] += v[p[i]];
	for (i = 0; i < n; ++i)
		cout<<num[i]<<endl;
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	read();
	solve();
	print();
	
	return 0;
}

整体二分

void solve(int L, int R, int beg, int end) {
	int mid = L + (R - L) / 2, i, bl = 0, br = 0, pl = 0, pr = 0, M;
	long long num;
	tag++;
	//printf("L = %d, R = %d, mid = %d\n", L, R, mid);
	if (L > R)	return;
	if (L == R) {
		for (i = beg; i < end; ++i)
			if (st[i].opt == 2) //iffffff
				ans[st[i].id] = L;
		return;
	}
	for (i = beg; i < end; ++i) {
		OPT &e = st[i];
		if (e.opt == 1) {
			if (e.k > mid) {
				add(e.a, e.b, 1);
				tr[pr++] = e;
			} else	tl[pl++] = e;
		} else {
			num = sum(e.a, e.b);
			//cout<<num<<endl;
			if (num >= e.k) {
				tr[pr++] = e;
				br = 1;
			} else {
				bl = 1;
				e.k -= num;
				tl[pl++] = e;
			}
		}
	}
	end = beg;
	for (i = 0; i < pl; ++i)	st[end++] = tl[i];
	M = end;
	for (i = 0; i < pr; ++i)	st[end++] = tr[i];
	if (bl)	solve(L, mid, beg, M);
	if (br) solve(mid + 1, R, M, end);
	return;
}
signed main() {
	int m, Q = 0;
	long long mn = 0x7f7f7f7f, mx = -0x7f7f7f7f;
	cin>>N>>m;
	for (int i = 0; i < m; ++i) {
		cin>>st[i].opt>>st[i].a>>st[i].b>>st[i].k;
		if (st[i].opt == 2)
			st[i].id = Q++;
		else {
			mn = min(mn, st[i].k);
			mx = max(mx, st[i].k);
		}
	}
	solve(mn, mx, 0, m);
	for (int i = 0; i < Q; ++i)
		cout<<ans[i]<<endl;
	return 0;
}

模拟退火

#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <ctime>
using namespace std;
double x;
time_t t0=clock();
double f(double x) {
	//return pow(x,5)*exp(x)+pow(x,2)*(-100)+pow(x,7)*(-81)-18;
	//return pow((x+1/x),x);
	return log(fabs(x))+log(2);
}
double delta(double d) {
	return fabs(f(d))-fabs(f(x));
}
void simulate_anneal();
int main() {
	srand(time(NULL));
	x=0;
	simulate_anneal();
	cout<<x<<endl;
	return 0;
}
void simulate_anneal() {
	double t=2000,k=0.99,i;
	while (t>1e-14) {
		double d=x+((rand()<<1)-RAND_MAX)*t;
		i=delta(d);
		if (i<0)
			x=d;
		else
			if (exp(-i/t)*RAND_MAX>rand())
				x=d;
		t*=k;
		if ((clock()-t0/(float)CLOCKS_PER_SEC)>0.15) {
			t0=clock();
			printf("d=%lf\tnowx=%lf\tf(x)=%lf\n",d,x,f(x));
		}
	}
	return;
}
posted @ 2019-11-06 10:46  BadPlayer  阅读(366)  评论(0编辑  收藏  举报