ACM算法模板整理

时间:2023-03-10 00:44:27
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;
}