queue<int>q;// 如果题目有偏序条件,可以改为优先队列
vector<int>a;
vector<int>e[N];voidtopsort(){for(int i =1; i <= n; i++){// 入度为0的节点入队if(!p[i]){
q.push(i);}}while(!q.empty()){int t = q.front();
q.pop();
a.push_back(t);for(auto&i : e[t]){
p[i]--;if(!p[i]){
q.push(i);}}}}
最小生成树
int n, m;// n 为节点数, m 为边数structnode{int a;int b;int w;}e[M];boolcmp(node a, node b){return a.w < b.w;}intkruskal(){int res =0, cnt =0;for(int i =0; i <= n; i++) p[i]= i;sort(e +1, e +1+ m; cmp);for(int i =1; i <= m; i++){int a = e[i].a, b = e[i].b, w = e[i].w;if(find(a)!=find(b)){join(a, b);
res += w;
cnt++;}}return res;}
并查集
// 初始化操作for(int i =0; i <= n; i++){
p[i]= i;}// 查找,路径压缩intfind(int x){if(x == p[x])return x;return p[x]=find(p[x]);}// 合并操作voidjoin(int a,int b){int aa =find(a), bb =find(b);if(aa == bb)return;
p[aa]= bb;}
单源最短路 dij 堆优化
vector<node>e[N];voiddij(int s){
priority_queue< PII, vector<PII>, greater<PII>>q;for(int i =0; i <= n +1; i++){
d[i]= INF;
vis[i]=false;}
d[s]=0;
q.push({0, s});while(!q.empty()){
PII t = q.top();
q.pop();int u = q.second, dis = q.first;if(vis[u])continue;
vis[u]=true;for(auto&i : e[u]){if(d[i.v]> d[u]+ i.w){
d[i.v]= d[u]+ i.w;
q.push({d[i.v], i.v});}}}}
多源最短路 费得比尔曼算法
structEdge{int a, b, c;}edges[M];int n, m;int dist[N];int last[N];voidbellman_ford(){memset(dist,0x3f,sizeof dist);
dist[1]=0;for(int i =0; i < n; i ++){memcpy(last, dist,sizeof dist);for(int j =0; j < m; j ++){auto e = edges[j];
dist[e.b]=min(dist[e.b], last[e.a]+ e.c);}}}
int n, m;int color[N];
vector<int>e[N];booldfs(int u,int c){
color[u]= c;for(auto&i : e[u]){if(!color[i]){if(!dfs(i,3- c))returnfalse;}elseif(color[i]== c)returnfalse;}returntrue;}// 判图bool flag =true;for(int i =1; i <= n; i ++){if(!color[i]){if(!dfs(i,1)){
flag =false;break;}}}if(flag)puts("Yes");elseputs("No");
二分图 最大匹配
#include<bits/stdc++.h>usingnamespace std;constint N =1e5+5;#definelllonglong
vector<int>edge[505];
vector<int>match(505,0);
vector<bool>st(505,false);boolfind(int x){for(auto&i : edge[x]){if(!st[i]){
st[i]=true;if(!match[i]||find(match[i])){
match[i]= x;returntrue;}}}returnfalse;}intmain(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);int n, m, e;
cin >> n >> m >> e;int a, b;while(e--){
cin >> a >> b;
edge[a].push_back(b);}int sum =0;// 匹配时只需要找其中一个集合for(int i =1; i <= n; i++){
st.assign(505,false);if(find(i))sum++;}
cout << sum <<"\n";return0;}
二分图 最大匹配边权 KM算法
#include<bits/stdc++.h>usingnamespace std;#definelllonglongconstint INF =0x3f3f3f3f;constint N =2e5+10;
vector<int>match(50),lx(50,0),ly(50,0);
vector<bool>sx(50),sy(50);int a[50][50];int n, MIN;boolfind(int x){
sx[x]=true;for(int i =1; i <= n; i++){if(!sy[i]){if(lx[x]+ ly[i]== a[x][i]){
sy[i]=true;if(!match[i]||find(match[i])){
match[i]= x;returntrue;}}elseif(lx[x]+ ly[i]> a[x][i]){
MIN =min(MIN, lx[x]+ ly[i]- a[x][i]);}}}returnfalse;}intmain(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;int x;for(int i =1; i <= n; i++){for(int j =1; j <= n; j++){
cin >> x;
a[i][j]= x;}}for(int i =1; i <= n; i++){for(int j =1; j <= n; j++){
lx[i]=max(lx[i], a[i][j]);}}for(int i =1; i <= n; i++){while(1){
MIN = INF;
sx.assign(25,false);
sy.assign(25,false);if(find(i))break;for(int j =1; j <= n; j++){if(!sx[j])continue;
lx[j]-= MIN;}for(int j =1; j <= n; j++){if(!sy[j])continue;
ly[j]+= MIN;}}}int sum =0;for(int i =1; i <= n; i++){
sum += a[match[i]][i];}
cout << sum <<"\n";return0;}
voidget_primes(int n){int primes[1], cnt;// primes[]存储所有素数 bool st[1];// st[x]存储x是否被筛掉//上面两行开全局,1为Nfor(int i =2; i <= n; i ++){if(!st[i]) primes[cnt ++]= i;for(int j =0; primes[j]<= n / i; j ++){
st[primes[j]* i]=true;if(i % primes[j]==0)break;}}}
分解质因数
voiddivide(int x){for(int i =2; i <= x / i; i ++)if(x % i ==0){int s =0;while(x % i ==0) x /= i, s ++;
cout << i <<' '<< s << endl;}if(x >1) cout << x <<' '<<1<< endl;
cout << endl;}
最大公约数
intgcd(int a,int b){return b ?gcd(b, a % b): a;}
扩展欧几里得算法
// 求x, y,使得ax + by = gcd(a, b)intexgcd(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;}
快速幂
intqmi(int m,int k,int p){int res =1% p, t = m;while(k){if(k&1) res = res * t % p;
t = t * t % p;
k >>=1;}return res;}
卡特兰数
Cat[n]=C(2, n)/(n +1);
卢卡斯定理求组合数
ll qmi(ll m, ll k, ll p){
ll res =1% p, t = m;while(k){if(k&1) res = res * t % p;
t = t * t % p;
k >>=1;}return res % p;}
ll C(ll a, ll b, ll p){if(a < b)return0;
ll x =1, y =1;// x是分子,y是分母for(int i = a, j =1; j <= b; i --, j ++){
x =(ll)x * i % p;
y =(ll) y * j % p;}return x *(ll)qmi(y, p -2, p)% p;}
ll lucas(ll a, ll b, ll p){if(a < p && b < p)returnC(a, b, p);returnC(a % p, b % p, p)*lucas(a / p, b / p, p)% p;}
int tr1[N];// 维护a[i]前缀和int tr2[N];// 维护a[i] * i的前缀和intlowbit(int x){return x &(-x);}voidadd(int tr[],int x,int k){for(int i = x; i <= n; i +=lowbit(i)){
tr[i]+= k;}}// 求某点值intsum(int tr[],int x){int res =0;for(int i = x; i ; i -=lowbit(i)){
sum += tr[i];}}// 求区间和intprefix_sum(int x){returnsum(tr1, x)*(x +1)-sum(tr2, x);}//操作1 求单点值
cout <<sum(l)<<"\n";// 建树add(l, d),add(r +1,-d);//操作2 求区间和
cout <<prefix_sum(r)-prefix_sum(l -1);//建树 add(tr1, l, r),add(tr2, l, l * r);add(tr1, l +1,- r),add(tr2, l +1,(l +1)*- r);
线段树
//本模板的操作为 区间乘一个x, 区间加一个x
ll tr[N *4], b[N *4], mul[N *4];
ll a[N];
ll mod;voidbuild(int p,int l,int r){
mul[p]=1;if(l == r){
tr[p]= a[l];return;}int mid = l +((r - l)>>1);build(2* p, l, mid),build(2* p +1, mid +1, r);
tr[p]=(tr[p *2]+ tr[p *2+1])% mod;return;}voidpushup(int p){
tr[p]=(tr[p *2]+ tr[p *2+1])% mod;return;}voidpushdowm(int p,int s,int t){int m = s +((t - s)>>1);// 乘法懒惰标记if(mul[p]!=1){
mul[p *2]= mul[p *2]* mul[p]% mod;
mul[p *2+1]= mul[p *2+1]* mul[p]% mod;
b[p *2]= b[p *2]* mul[p]% mod;
b[p *2+1]= b[p *2+1]* mul[p]% mod;
tr[p *2]= tr[p *2]* mul[p]% mod;
tr[p *2+1]= tr[p *2+1]* mul[p]% mod;
mul[p]=1;}// 只有加法时候的模板if(b[p]){
tr[p *2]=(b[p]*(m - s +1)+ tr[p *2])% mod;
tr[p *2+1]=(b[p]*(t - m)+ tr[p *2+1])% mod;
b[p *2]=(b[p]+ b[p *2])% mod;
b[p *2+1]=(b[p]+ b[p *2+1])% mod;
b[p]=0;}return;}voidupdate1(int l,int r, ll c,int s,int t,int p){if(l <= s && t <= r){
tr[p]+=(t - s +1)* c, b[p]+= c;
tr[p]%= mod, b[p]%= mod;return;}pushdowm(p, s, t);int m = s +((t - s)>>1);if(l <= m)update1(l, r, c, s, m, p *2);if(r > m)update1(l, r, c, m +1, t, p *2+1);pushup(p);return;}voidupdate2(int l,int r, ll c,int s,int t,int p){if(l <= s && t <= r){
tr[p]*= c, b[p]*= c, mul[p]*= c;
tr[p]%= mod, b[p]%= mod, mul[p]%= mod;return;}pushdowm(p, s, t);int m = s +((t - s)>>1);if(l <= m)update2(l, r, c, s, m, p *2);if(r > m)update2(l, r, c, m +1, t, p *2+1);pushup(p);return;}
ll getsum(int l,int r,int s,int t,int p){if(l <= s && t <= r)return tr[p];int m = s +((t - s)>>1);pushdowm(p, s, t);
ll sum =0;if(l <= m) sum +=getsum(l, r, s, m, p *2);
sum %= mod;if(r > m) sum +=getsum(l, r, m +1, t, p *2+1);return sum % mod;}
模拟散列表之开放寻址法
ull find(ull x){
ull t =(x % N + N)% N;while(h[t]!= INF && h[t]!= x){
t++;if(t == N) t =0;}return t;}
字符串HASH
#defineullunsignedlonglongconstint N =1e5+11;const ull P =131;
ull h[N], p[N], a[N];
string s;
ull get(int l,int r){return h[r]- h[l -1]* p[r - l +1];}
ull Hash(){int k = s.size();
p[0]=1;for(int i =1; i <= k; i ++){
h[i]= h[i -1]* P +(ull)s[i -1];
p[i]= p[i -1]* P;}returnget(1, k);}//如果爆ll :#defineullunsignedlonglongconst ull P =233;constint N =2e6+10;const ull mod =99989397;
ull h[N], p[N], a[N];
string s;
ull get(int l,int r){return(h[r]- h[l -1]* p[r - l +1]% mod + mod)% mod;}
ull Hash(){int k = s.size();
p[0]=1;for(int i =1; i <= k; i ++){
h[i]=((h[i -1]* P)% mod +(ull)s[i -1])% mod;
p[i]=(p[i -1]* P)% mod;}returnget(1, k);}
Trie树
int nex[N][65], cnt, a[N];int n, m;intgetval(char c){if(c >='A'&& c <='Z'){return(c -'A');}elseif(c >='a'&& c <='z'){return(c -'a'+26);}else{return(c -'0'+52);}}voidinsert(string s){int p =0;for(int i =0; i < s.size(); i++){int c =getval(s[i]);if(!nex[p][c]) nex[p][c]=++cnt;
p = nex[p][c];
a[p]++;}return;}intfind(string s){int p =0;for(int i =0; i < s.size(); i++){int c =getval(s[i]);if(!nex[p][c])return0;
p = nex[p][c];}return a[p];}
Trie数之最大异或与最小异或
#definelllonglongconstint N =1e5+10;#definePIIpair<int,int>const ll INF =0x3f3f3f3f;int nex[N *32][2], a[N *32], ep[N *32];int cnt;voidinsert(ll s){int p =0;for(int i =31; i >=0; i--){int c = s >> i &1;if(nex[p][c]==-1)
nex[p][c]=++cnt;
p = nex[p][c];}return;}//最大异或
ll find1(ll s){
ll ans = s;int p =0;for(int i =31; i >=0; i--){int c = s >> i &1;if(nex[p][!c]!=-1){
ans ^=((!c)<< i);
p = nex[p][!c];}else{
ans ^=(c << i);
p = nex[p][c];}}return ans;}// 最小异或
ll find2(ll s){
ll ans = s;int p =0;for(int i =31; i >=0; i--){int c = s >> i &1;if(nex[p][c]!=-1){
ans ^=((c)<< i);
p = nex[p][c];}else{
ans ^=((!c)<< i);
p = nex[p][!c];}}return ans;}voidsolve(int u){memset(nex,-1,sizeof nex);
cnt =0;int n;
cin >> n;
ll sum =0;
ll ans1 =-INF;
ll ans2 = INF;insert(0);
ll x;while(n--){
cin >> x;
sum ^= x;
ans2 =min(ans2,find2(sum));insert(sum);
ans1 =max(ans1,find1(sum));}
cout <<"Case "<< u <<": "<< ans1 <<" "<< ans2 <<"\n";return;}
主席树
constint maxn =1e5;// 数据范围int tot, n, m;int sum[(maxn <<5)+10], rt[maxn +10], ls[(maxn <<5)+10],
rs[(maxn <<5)+10];int a[maxn +10], ind[maxn +10], len;intgetid(constint&val){// 离散化returnlower_bound(ind +1, ind + len +1, val)- ind;}intbuild(int l,int r){// 建树int root =++tot;if(l == r)return root;int mid = l + r >>1;
ls[root]=build(l, mid);
rs[root]=build(mid +1, r);return root;// 返回该子树的根节点}intupdate(int k,int l,int r,int root){// 插入操作int dir =++tot;
ls[dir]= ls[root], rs[dir]= rs[root], sum[dir]= sum[root]+1;if(l == r)return dir;int mid = l + r >>1;if(k <= mid)
ls[dir]=update(k, l, mid, ls[dir]);else
rs[dir]=update(k, mid +1, r, rs[dir]);return dir;}intquery(int u,int v,int l,int r,int k){// 查询操作int mid = l + r >>1,
x = sum[ls[v]]- sum[ls[u]];// 通过区间减法得到左儿子中所存储的数值个数if(l == r)return l;if(k <= x)// 若 k 小于等于 x ,则说明第 k 小的数字存储在在左儿子中returnquery(ls[u], ls[v], l, mid, k);else// 否则说明在右儿子中returnquery(rs[u], rs[v], mid +1, r, k - x);}
f[0]=-0x3f3f3f3f;int len =0;int mid;int ans;for(int i =0; i < cnt; i++){int l =0, r = len;while(l < r){
mid =(l + r +1)/2;if(f[mid]< a[i]){
l = mid;}else{
r = mid -1;}}
len =max(len,r +1);
f[r +1]= a[i];}
杂项
取模板子(源自jiangly)
using ll =longlong;//快速幂template<classT>constexpr T qmi(T a, ll b){
T res {1};for(; b; b /=2, a *= a){if(b %2){
res *= a;}}return res;}constexpr ll mul(ll a, ll b, ll p){
ll res = a * b -ll(1.L* a * b / p)* p;
res %= p;if(res <0){
res += p;}return res;}template<ll P>structMInt{
ll x;constexprMInt(): x {0}{}constexprMInt(ll x): x {norm(x %getMod())}{}static ll Mod;constexprstatic ll getMod(){if(P >0){return P;}else{return Mod;}}constexprstaticvoidsetMod(ll Mod_){
Mod = Mod_;}constexpr ll norm(ll x)const{if(x <0){
x +=getMod();}if(x >=getMod()){
x -=getMod();}return x;}constexpr ll val()const{return x;}constexpr MInt operator-()const{
MInt res;
res.x =norm(getMod()- x);return res;}constexpr MInt inv()const{returnpower(*this,getMod()-2);}constexpr MInt &operator*=(MInt rhs)&{if(getMod()<(1ULL<<31)){
x = x * rhs.x %int(getMod());}else{
x =mul(x, rhs.x,getMod());}return*this;}constexpr MInt &operator+=(MInt rhs)&{
x =norm(x + rhs.x);return*this;}constexpr MInt &operator-=(MInt rhs)&{
x =norm(x - rhs.x);return*this;}constexpr MInt &operator/=(MInt rhs)&{return*this*= rhs.inv();}friendconstexpr MInt operator*(MInt lhs, MInt rhs){
MInt res = lhs;
res *= rhs;return res;}friendconstexpr MInt operator+(MInt lhs, MInt rhs){
MInt res = lhs;
res += rhs;return res;}friendconstexpr MInt operator-(MInt lhs, MInt rhs){
MInt res = lhs;
res -= rhs;return res;}friendconstexpr MInt operator/(MInt lhs, MInt rhs){
MInt res = lhs;
res /= rhs;return res;}friendconstexpr std::istream &operator>>(std::istream &is, MInt &a){
ll v;
is >> v;
a =MInt(v);return is;}friendconstexpr std::ostream &operator<<(std::ostream &os,const MInt &a){return os << a.val();}friendconstexprbooloperator==(MInt lhs, MInt rhs){return lhs.val()== rhs.val();}friendconstexprbooloperator!=(MInt lhs, MInt rhs){return lhs.val()!= rhs.val();}friendconstexprbooloperator<(MInt lhs, MInt rhs){return lhs.val()< rhs.val();}};template<>
ll MInt<0>::Mod =998244353;constexprint P =998244353;//设置模数using Z = MInt<P>;
boolcheck(int x){};int l, r;//左右边界int mid, ans =-1;while(l <= r){
mid = l +((r - l)>>1);if(check()){//如果求最小答案
r = mid -1;
ans = mid;//如果求最大答案
l = mid +1;
ans = mid
}else{//如果求最小答案
l = mid +1;//如果求最大答案
r = mid -1;}}