模板大全(持续更新)

快速读入

#include<bits/stdc++.h>
using namespace std;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin)),*p1++)
inline int read(){
    int x = 0,f = 1;
    char ch = gc();
    while(ch < '0' || ch > '9'){
        if (ch == '-')f = -1;
        ch = gc();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch - '0');
        ch = gc();
    }
    return x * f;
}
inline void write(int x){
    if (x < 0)x *= -1,putchar('-');
    if (x > 9)write(x / 10);
    putchar(x % 10 + '0');
    return ;
}
signed main(){
    int x = read();
    write(x);
    return 0;
}

快速幂

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353;
inline ll ksm(ll a,ll b){
    ll ans = 1;
    while(b){
        if (b & 1)ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans % mod;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    ll x,y;
    cin >> x >> y;
    cout << ksm(x,y);
    return 0;
}

素数筛

埃氏筛

#include<bits/stdc++.h>
using namespace std;
int n;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    vector<int> isp(n+1,true);
    isp[0] = isp[1] = false;
    isp[2] = true;
    for(int i = 2;i * i <= n; i++){
        if (isp[i]){
            for(int j = i * i;j <= n;j += i){
                isp[j] = false;
            }
        }
    }
    for(int i = 1;i <= n;i ++){
        if (isp[i]){
            cout << i <<" ";
        }
    }
    return 0;
}

欧拉筛

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,tot,zx[N];
//zx[i]保存 i 的最小质因数
vector<int> isp(N,true);
vector<int> pri;
inline void ols(){
    for(int i = 2;i <= n;i ++){
        if (isp[i]){
            tot ++;
            pri.push_back(i);
            zx[i] = i;
        }
        for(auto j : pri){
            if (j > n / i)break;//防止 i * j 炸 int
            isp[i * j] = false;
            zx[i * j] = j;
            if (i % j == 0)break;//每次只用最小质因子筛
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    isp[0] = isp[1] = false;
    isp[2] = true;
    ols();
    for(auto i : pri){
        cout << i << " ";
    }
    cout << "\n";
    for(int i = 2;i <= n;i ++){
        cout << zx[i] << " ";
    }
    return 0;
}

背包问题

完全背包

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n,m,w[N],v[N],f[N];
//n 物品数量,m 背包容量,v[i] 第 i 个物品体积,w[i] 第 i 个物品价值
//f[i][j] 选到第 i 件物品,背包此时容量为 j 的最大价值
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    for(int i = 1;i <= n;i ++){
        cin >> v[i] >> w[i];
    }
    for(int i = 1;i <= n;i ++){
        for(int j = w[i];j <= m;j ++){
            f[j] = max(f[j - w[i]] + v[i],f[j]);
        }
    }
    return 0;
}

01背包

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n,m,w[N],v[N],f[N];
//n 物品数量,m 背包容量,v[i] 第 i 个物品体积,w[i] 第 i 个物品价值
//f[i][j] 选到第 i 件物品,背包此时容量为 j 的最大价值
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    for(int i = 1;i <= n;i ++){
        cin >> v[i] >> w[i];
    }
    for(int i = 1;i <= n;i ++){
        for(int j = m;j >= w[i];j --){
            f[j] = max(f[j - w[i]] + v[i],f[j]);
        }
    }
    return 0;
}

上升下降子序列

int cnt = 0;
for(int i = 1;i <= n;i ++){
	if (a[i] >= sheng[cnt]){
		sheng[++cnt] = a[i];
	}else{
		sheng[upper_bound(sheng + 1,sheng + 1 + cnt,a[i]) - sheng] = a[i];
	}
}
cout << cnt;
  //最长非下降子序列模版
int cnt = 0;
for(int i = 1;i <= n;i ++){
	if (b[i] >= jiang[cnt]){
		jiang[++cnt] = b[i];
	}else{
		jiang[upper_bound(jiang + 1,jiang + 1 + cnt,b[i]) - jiang] = b[i];
	}
}
cout << cnt;
  //最长非上升子序列模版
int cnt = 0;
for(int i = 1;i <= n;i ++){
	if (a[i] > sheng[cnt]){
		sheng[++cnt] = a[i];
	}else{
		sheng[lower_bound(sheng + 1,sheng + 1 + cnt,a[i]) - sheng] = a[i];
	}
}
cout << cnt;
  //最长上升子序列模版
int cnt = 0;
for(int i = 1;i <= n;i ++){
	if (b[i] > jiang[cnt]){
		jiang[++cnt] = b[i];
	}else{
		jiang[lower_bound(jiang + 1,jiang + 1 + cnt,b[i]) - jiang] = b[i];
	}
}
cout << cnt;
  //最长下降子序列模版
  
for(int i = 1;i <= n;i ++){
	cin >> a[i];
}
for(int i = 1;i <= n;i ++){
	b[i] = a[n-i+1];
}
  //b[ ]为a[ ]的倒序数组

归并排序

#include<bits/stdc++.h>
using namespace std;
int n;
int a[100005];
int b[100005];
void merge(int l,int r,int m){
	int i = l,j = m + 1;
	int cnt = l;
	while(i <= m and j <= r){
		if (a[i] < a[j]){
			b[cnt] = a[i];
			i ++;
		}else{
			b[cnt] = a[j];
			j ++;
		}
		cnt ++;
	}
	while(i <= m){
		b[cnt] = a[i];
		i ++;
		cnt ++;
	}
	while(j <= r){
		b[cnt] = a[j];
		j ++;
		cnt ++;
	}
	for(int k = l;k <= r;k ++){
		a[k] = b[k];
	}
}
void bsort(int l,int r){
	if (l >= r)return;
	int m = (l + r) / 2;
	bsort(l,m);
	bsort(m + 1,r);
	merge(l,r,m);//合并左右部分 
}
int main(){
	cin >> n;
	for(int i = 1;i <= n;i ++){
		cin >> a[i];
	}
	bsort(1,n);
	for(int i = 1;i <= n;i ++){
		cout << a[i] << " ";
	}
    return 0;
}

最短路

floyd

#include<bits/stdc++.h>
using namespace std;
const int N=105;
int n,m,dis[N][N];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    memset(dis,0x3f,sizeof(dis));
    for(int i = 1;i <= m;i ++){
        int u,v,d;
        cin >> u >> v >> d;
        dis[u][v] = min(dis[u][v],d);
        dis[v][u] = min(dis[v][u],d);
    }
    for(int i = 1;i <= n;i ++)dis[i][i] = 0;
    for(int k = 1;k <= n;k ++){
        for(int i = 1;i <= n;i ++){
            for(int j = 1;j <= n;j ++){
                dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
            }
        }
    }
    for(int i = 1;i <= n;i ++){
        for(int j = 1;j <= n;j ++){
            cout << dis[i][j] << " ";
        }
        cout << "\n";
    }
    return 0;
}

dijkstra 朴素

#include<bits/stdc++.h>
using namespace std;
struct node{
	int y,v;
	node(int _y,int _v){
		y = _y,v = _v;
	}
};
vector<node>edge[5003];
int n,m,k,dist[5003];
bool b[5003];
inline void dijkstra(int s,int t){
	memset(b,false,sizeof(b));
	memset(dist,127,sizeof(dist));
	dist[s]=0;
	for(;;){
		int x = -1;
		for(int i = 1;i <= n;i ++){
			if (!b[i] and dist[i] < 1 << 30 ){
				if (x == -1 or dist[i] < dist[x]){
					x = i;
				}
			}
		}
		if (x == t or x == -1){
			break;
		}
		b[x] = true;
		for(auto i : edge[x]){
			dist[i.y] = min(dist[i.y],dist[x] + i.v);
		}
		
	}
	if (dist[t] < 1 << 30){
		cout << dist[t] << "\n";
	}else{
		cout << -1 << "\n";
	}
}
int main(){
	cin >> n >> m >> k;
	for(int i = 1;i <= m;i ++){
		int x,y,z;
		cin >> x >> y >> z;
		edge[x].push_back(node(y,z));
	}
	for(int i = 1;i <= k;i ++){
		int s,t;
		cin >> s >> t;
		dijkstra(s,t);
	}
	return 0;
}

dijkstra 堆优化

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, q;
struct node{ int to, d; };
vector<node> e[N];
inline void dijkstra(int s, int t){
    static int  dist[N];
    static bool vis[N];
    memset(dist, 0x3f, sizeof(int ) * (n + 1));   
    memset(vis , 0   , sizeof(bool) * (n + 1));
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq;
    dist[s] = 0;
    pq.push({0, s});
    while(!pq.empty()){
        pair<int,int> p = pq.top(); pq.pop();
        int d = p.first, u = p.second;
        if(vis[u]) continue;      
        vis[u] = true;
        if(u == t) break;         
        for(auto &nx : e[u]){
            int v = nx.to, w = nx.d;
            if(dist[v] > d + w){  
                dist[v] = d + w;
                pq.push({dist[v], v});
            }
        }
    }
    cout << dist[t] << '\n';
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> q;
    for(int i = 1; i < n; i++){
        int u, v, w;
        cin >> u >> v >> w;
        e[u].push_back({v, w});
        e[v].push_back({u, w});
    }
    while(q--){
        int from, to;
        cin >> from >> to;
        dijkstra(from, to);
    }
    return 0;
}

哈希

字符串哈希

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int P=0xccf54188 - 1;
int n;
int mi[2005],cnt;
unordered_map<int,bool>mp;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	mi[0] = 1;
	for(int i = 1;i <= 2000; i++){
		mi[i] = mi[i - 1] * 127 % P;
	} 
	for(int i = 1;i <= n; i++){
		string s;
		int key = 0;
		cin >> s;
		for(int j = 0;j < s.size(); j++){
			key += (s[j] - '0') * mi[j];
			key %= P;
		}
		if (mp[key] == false)cnt++;
		mp[key] = true;
	}
	cout << cnt;
	return 0;
}

哈希表

拉链法

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int T = 1e7 + 19;
const int N = 5e6 + 5;
int h[T],ne[N],idx = 0,n;
ull key[N],val[N],x,y,ans;
struct hash{
	inline void init(){
		memset(h,-1,sizeof(h));
	}
	ull find(ull x){
		int k = (int)(x % T);
		for(int i = h[k];i != -1;i = ne[i]){
			if (key[i] == x){
				return val[i];
			}
		}
		return 0;
	}
	inline void insert(ull x,ull y){
		int k = (int)(x % T);
		for(int i = h[k];i != -1;i = ne[i]){
			if (key[i] == x){
				val[i] = y;
				return;
			}
		}
		key[idx] = x;
		val[idx] = y;
		ne[idx] = h[k];
		h[k] = idx++;
	} 
}hh;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	hh.init();
	for(int i = 1;i <= n;i++){
		cin >> x >> y;
		ans += (ull)i * hh.find(x);
		hh.insert(x,y);
	}
	cout << ans;
	return 0;
}

开放寻址法

#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long 
const int N = 1e7+19;
int t,x,y,ans,i = 1;
struct hash_table{
	int h[N],val[N];
	bool used[N];
	inline void init(){
		memset(used,0,sizeof(used));
		return;
	}
	inline int find(int x){
		int k = x%N;
		while(used[k] and h[k] != x){
			k++;
			if (k == N)k = 0;
		}
		return k;
	}
	inline int query(int x){
		int k = find(x);
		return used[k] ? val[k] : 0;
	}
	inline void insert(int x,int y){
		int k = find(x);
		used[k] = 1;
		h[k] = x;
		val[k] = y;
		return;
	}
}hs;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	hs.init();
	while(t--){
		cin >> x >> y;
		ans += i * hs.query(x);
		hs.insert(x,y);
		i++;
	}
	cout << ans;
	return 0;
}

单调栈

#include<bits/stdc++.h>
using namespace std;
const int N = 3e6+5;
int n,a[N],ans[N];
stack<int>st;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    for(int i = 1;i <= n;i++){
        cin >> a[i];
    }
    for(int i = 1;i <= n;i++){
        while(!st.empty() and a[st.top()] < a[i]){
            ans[st.top()] = i;
            st.pop();
        }
        st.push(i);
    }
    for(int i = 1;i <= n;i++){
        cout << ans[i] << " ";
    }
    return 0;
}

单调队列

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
deque<int>dq;
int n,k,a[N],minn[N],maxn[N];
signed main(){
    cin >> n >> k;
    for(int i = 1;i <= n;i++){
        cin >> a[i];
    }
    for(int i = 1;i <= n;i++){
        if (!dq.empty() and i - dq.front() + 1 > k)dq.pop_front();
        while(!dq.empty() and a[dq.back()] > a[i])dq.pop_back();
        dq.push_back(i);
        if (i - k >= 0){
            minn[i - k + 1] = dq.front();
        }
    }
    dq.clear();
    for(int i = 1;i <= n;i++){
        if (!dq.empty() and i - dq.front() + 1 > k)dq.pop_front();
        while(!dq.empty() and a[dq.back()] < a[i])dq.pop_back();
        dq.push_back(i);
        if (i - k >= 0){
            maxn[i - k + 1] = dq.front();
        }
    }
    for(int i = 1;i <= n - k + 1;i++){
        cout << a[minn[i]] << " ";
    }
    cout << "\n";
    for(int i = 1;i <= n - k + 1;i++){
        cout << a[maxn[i]] << " ";
    }
    return 0;
}

树状数组

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int N = 5e5 + 5;
int n,m,a[N],s[N];
inline int lowbit(int x){
	return x & -x;
}
inline void update(int pos,int val){
	for(int i = pos;i <= n;i += lowbit(i)){
		s[i] += val;
	}
}
inline int query(int pos){
	int ans = 0;
	for(int i = pos;i;i -= lowbit(i)){
		ans += s[i];
	}
	return ans;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= n;i++){
		cin >> a[i];
		update(i,a[i]);
	}
	while(m--){
		int op;
		cin >> op;
		if (op == 1){
			int pos,val;
			cin >> pos >> val;
			update(pos,val);
		}else{
			int l,r;
			cin >> l >> r;
			cout << query(r) - query(l-1) << "\n";
		}
	}
	return 0;
}

线段树

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define ls (rt << 1)
#define rs (rt << 1 | 1)
const int N = 1e5 + 5;
struct tree{
	int l,r,sum,lazy;
}t[N << 2];
int n,m,a[N];
inline void pushup(int rt){
	t[rt].sum = t[ls].sum + t[rs].sum;
}
inline void apply(int rt,int lz){
	t[rt].sum += lz * (t[rt].r - t[rt].l + 1);
	t[rt].lazy += lz;
}
inline void pushdown(int rt){
	int lz = t[rt].lazy;
	t[rt].lazy = 0;
	apply(ls,lz);
	apply(rs,lz);
}
inline void build(int rt,int l,int r){
	t[rt].l = l,t[rt].r = r;
	if (l == r){
		t[rt].sum = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(rt);
}
inline void update(int rt,int l,int r,int val){
	if (l <= t[rt].l and t[rt].r <= r){
		apply(rt,val);
		return;
	}
	pushdown(rt);
	int mid = (t[rt].l + t[rt].r) >> 1;
	if (l <= mid)update(ls,l,r,val);
	if (mid < r)update(rs,l,r,val);
	pushup(rt);
}
inline int query(int rt,int l,int r){
	if (l <= t[rt].l and t[rt].r <= r){
		return t[rt].sum;
	}
	pushdown(rt);
	int mid = (t[rt].l + t[rt].r) >> 1,ans = 0;
	if (l <= mid)ans += query(ls,l,r);
	if (mid < r)ans += query(rs,l,r);
	return ans;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= n;i++){
		cin >> a[i];
	}
	build(1,1,n);
	while(m--){
		int op;
		cin >> op;
		if (op == 1){
			int x,y,val;
			cin >> x >> y >>val;
			update(1,x,y,val);
		}else{
			int l,r;
			cin >> l >> r;
			cout << query(1,l,r) << "\n";
		}
	}
	return 0;
}

最近公共祖先

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int n,m,s,d[N],f[N][21];
vector<int>e[N];
inline void dfs(int u,int fa){
	d[u] = d[fa] + 1;
	f[u][0] = fa;
	for(auto v : e[u]){
		if (v == fa)continue;
		dfs(v,u);
	}
}
inline void init(){
	for(int j = 1;j <= 20;j++){
		for(int i = 1;i <= n;i++){
			f[i][j] = f[f[i][j-1]][j-1];
		}
	}
}
inline int lca(int x,int y){
	if (d[x] > d[y])swap(x,y);
	for(int i = 20;i >= 0;i--){
		if (d[x] <= d[f[y][i]]){
			y = f[y][i];
		}
	}
	if (x == y)return x;
	for(int i = 20;i >= 0;i--){
		if (f[x][i] == f[y][i]){
			continue;
		}else{
			x = f[x][i];
			y = f[y][i];
		}
	}
	return f[x][0];
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m >> s;
	for(int i = 1;i <= n - 1;i++){
		int u,v;
		cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	dfs(s,0);
	init();
	while(m--){
		int x,y;
		cin >> x >> y;
		cout << lca(x,y) << "\n";
	}
	return 0;
}

最小生成树

#include<bits/stdc++.h>
using namespace std;
const int N = 5e3 + 5;
int n,m,t,ans,fa[N];
struct node{
	int from,to,dis;
};
vector<node>e;
inline bool cmp(node x,node y){
	return x.dis < y.dis;
}
inline int find(int x){return (fa[x] == x ? x : fa[x] = find(fa[x]));}
signed main(){ 
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= m;i++){
		int u,v,dis;
		cin >> u >> v >> dis;
		e.push_back({u,v,dis});
	}
	for(int i = 1;i <= n;i++)fa[i] = i;
	sort(e.begin(),e.end(),cmp);
	for(auto i : e){
		int u = i.from,v = i.to,dis = i.dis;
		int fu = find(u),fv = find(v);
		if (fu != fv){
			fa[fu] = fv;
			t++;
			ans += dis;
		}
		if (t == n-1){
			cout << ans;
			exit(0);
		}
	}
	cout<<"orz";
	return 0;
}

拓扑排序

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
int n,in[N];
vector<int>e[N];
queue<int>q;
inline void tp(){
	while(!q.empty()){
		int u = q.front();
		q.pop();
		cout << u << " ";
		for(auto v : e[u]){
			in[v]--;
			if (in[v] == 0)q.push(v);
		}
	}
}
signed main(){ 
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for(int i = 1;i <= n;i++){
		while(1){
			int x;
			cin >> x;
			if (x == 0)break;
			e[i].push_back(x);
			in[x]++;
		}
	}
	for(int i = 1;i <= n;i++){
		if (in[i] == 0)q.push(i);
	}
	tp();
	return 0;
}

tarjan

tarjan 求割点

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n,m,times,dfn[N],low[N];
bool isgd[N];
vector<int>gd;
vector<int>e[N];
inline void dfs(int u,int fa){
	dfn[u] = low[u] = ++times;
	int cntson = 0;
	bool iscut = false;
	for(auto v : e[u]){
		if (v == fa)continue;
		if (!dfn[v]){
			cntson++;
			dfs(v,u);
			low[u] = min(low[u],low[v]);
			if (fa != 0 and low[v] >= dfn[u]){
				iscut = true;
			}
		}else{
			low[u] = min(low[u],dfn[v]);
		}
	}
	if (fa == 0 and cntson >= 2){
		iscut = true;
	}
	if (iscut == true and isgd[u] == false){
		gd.push_back(u);
		isgd[u] = true;
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= m;i++){
		int u,v;
		cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	for(int i = 1;i <= n;i++){
		if (!dfn[i]){
			dfs(i,0);
		}
	}
	sort(gd.begin(),gd.end());
	cout << gd.size() << "\n";
	for(auto i : gd){
		cout << i << " ";
	}
	return 0;
}

tarjan 求割边

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
struct node{
	int to,id;
};
int n,m,dfn[N],low[N],times;
vector<node>e[N];
vector<int>gb;
inline void dfs(int u,int fa){
	dfn[u] = low[u] = ++times;
	for(auto i : e[u]){
		int v = i.to;
		if (v == fa)continue;
		if (!dfn[v]){
			dfs(v,u);
			low[u] = min(low[u],low[v]);
			if (low[v] > dfn[u])gb.push_back(i.id);
		}else{
			low[u] = min(low[u],dfn[v]);
		}
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= m;i++){
		int u,v;
		cin >> u >> v;
		e[u].push_back({v,i});
		e[v].push_back({u,i});
	}
	for(int i = 1;i <= n;i++){
		if (!dfn[i]){
			dfs(i,0);
		}
	}
	cout << gb.size() << "\n";
	sort(gb.begin(),gb.end());
	for(auto i : gb){
		cout << i << " ";
	}
	return 0;
}

tarjan 求边双连通分量

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5+5;
int n,m,dfn[N],low[N],times;
struct node{
	int to,id;
};
vector<node>e[N];
vector<vector<int>>ans;
stack<int>st;
inline void dfs(int u,int lst){
	dfn[u] = low[u] = ++times;
	st.push(u);
	for(auto i : e[u]){
		int v = i.to,nxt = i.id;
		if (nxt == (lst^1))continue;
		if (!dfn[v]){
			dfs(v,nxt);
			low[u] = min(low[u],low[v]);
		}else{
			low[u] = min(low[u],dfn[v]);
		}
	}
	if (dfn[u] == low[u]){
		vector<int>res;
		res.push_back(u);
		while(st.top() != u){
			res.push_back(st.top());
			st.pop();
		}
		st.pop();
		ans.push_back(res);
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= m;i++){
		int u,v;
		cin >> u >> v;
		e[u].push_back({v,i << 1});
		e[v].push_back({u,i << 1|1});
	}
	for(int i = 1;i <= n;i++){
		if (!dfn[i]){
			dfs(i,0);
		}
	}
	cout << ans.size() << "\n";
	for(auto i : ans){
		cout << i.size() << " ";
		for(auto j : i)cout << j << " ";
		cout << "\n";
	}
	return 0;
}

tarjan 求点双连通分量

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5+5;
const int M = 2e6+5;
int n,m,dfn[N],low[N],times;
vector<int>e[M];
vector<vector<int>>ans;
stack<int>st;
inline void dfs(int u,int fa){
	dfn[u] = low[u] = ++times;
	st.push(u);
	if (fa == 0 and e[u].empty()){
		ans.push_back({u});
		return;
	}
	for(auto v : e[u]){
		if (v == fa)continue;
		if (!dfn[v]){
			dfs(v,u);
			low[u] = min(low[u],low[v]);
			if (low[v] >= dfn[u]){
				vector<int>res;
				int topp;
				do{
					topp = st.top();
					st.pop();
					res.push_back(topp);
				}while(topp != v);
				res.push_back(u);
				ans.push_back(res);
			}
		}else{
			low[u] = min(low[u],dfn[v]);
		}
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= m;i++){
		int u,v;
		cin >> u >> v;
		if (u == v)continue;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	for(int i = 1;i <= n;i++){
		if (!dfn[i]){
			times = 0;
			dfs(i,0);
		}
	}
	cout << ans.size() << "\n";
	for(auto i : ans){
		cout << i.size() << " ";
		for(auto j : i)cout << j << " ";
		cout << "\n";
	}
	return 0;
}

tarjan 求强连通分量

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int n,m,a[N];
vector<int>e[N];
vector<int>g[N];
int dfn[N],low[N],times,belong[N],from[N],to[N],dp[N],in[N];
bitset<N>ins;
stack<int>st;
inline void tarjan(int u){
	dfn[u] = low[u] = ++times;
	st.push(u);
	ins[u] = true;
	for(auto v : e[u]){
		if (!dfn[v]){
			tarjan(v);
			low[u] = min(low[u],low[v]);
		}else if(ins[v]){
			low[u] = min(low[u],dfn[v]);
		}
	}
	if (low[u] == dfn[u]){
		int topp;
		do{
			topp = st.top();
			st.pop();
			belong[topp] = u;
			ins[topp] = false;
			if (topp != u) a[u] += a[topp];
		}while(u != topp);
	}
}
inline void tp(){
	queue<int>q;
	for(int i = 1;i <= n;i++){
		if (i == belong[i] and in[i] == 0){
			q.push(i);
			dp[i] = a[i];
		}
	}
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(auto v:g[u]){
			dp[v] = max(dp[v],dp[u]+a[v]);
			if (--in[v] == 0)q.push(v);
		}
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for(int i = 1;i <= n;i++)cin >> a[i];
	for(int i = 1;i <= m;i++){
		int u,v;
		cin >> u >> v;
		e[u].push_back(v);
		from[i] = u,to[i] = v;
	}
	for(int i = 1;i <= n;i++){
		if (!dfn[i])tarjan(i);
	}
	for(int i = 1;i <= m;i++){
		int x = belong[from[i]],y = belong[to[i]];
		if (x != y){
			g[x].push_back(y);
			in[y]++;
		}
	}
	tp();
	int ans = -1;
	for(int i = 1;i <= n;i++){
		ans = max(ans,dp[i]);
	}
	cout << ans;
	return 0;
}

树链剖分

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ls (rt << 1)
#define rs (rt << 1 | 1)
const int N = 1e5 + 5;
int n,m,mod,r,a[N];
vector<int>e[N];
int d[N],f[N],siz[N],son[N];
int id[N],w[N],top[N],times;
struct tree{
    int l,r;
    ll sum,lazy;
}t[N << 2];
inline void dfs1(int u,int fa){
    d[u] = d[fa] + 1;
    f[u] = fa;
    siz[u] = 1;
    int maxson = -1;
    for(auto v:e[u]){
        if (v == fa)continue;
        dfs1(v,u);
        siz[u] += siz[v];
        if (siz[v] > maxson){
            maxson = siz[v];
            son[u] = v;
        }
    }
}
inline void dfs2(int u,int topf){
    id[u] = ++times;
    w[times] = a[u];
    top[u] = topf;
    if (son[u] == 0)return;
    dfs2(son[u],topf);
    for(auto v:e[u]){
        if (v == f[u] or v == son[u])continue;
        dfs2(v,v);
    }
}
inline void pushup(int rt){
    t[rt].sum = t[ls].sum + t[rs].sum;
    t[rt].sum %= mod;
}
inline void pushdown(int rt){
    if (t[rt].lazy){
        ll lz = t[rt].lazy;
        t[rt].lazy = 0;
        t[ls].lazy += lz;
        t[rs].lazy += lz;
        t[ls].sum += lz * (t[ls].r - t[ls].l + 1);
        t[rs].sum += lz * (t[rs].r - t[rs].l + 1);
        t[ls].lazy %= mod;
        t[rs].lazy %= mod;
        t[ls].sum %= mod;
        t[rs].sum %= mod;
    }
}
inline void build(int rt,int l,int r){
    t[rt].l = l,t[rt].r = r;
    if (l == r){
        t[rt].sum = w[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(ls,l,mid);
    build(rs,mid + 1,r);
    pushup(rt);
}
inline void update(int rt,int l,int r,int val){
    if (l <= t[rt].l and t[rt].r <= r){
        t[rt].lazy += val;
        t[rt].sum += val * (t[rt].r - t[rt].l + 1);
        t[rt].lazy %= mod;
        t[rt].sum %= mod;
        return;
    }
    pushdown(rt);
    int mid = (t[rt].l + t[rt].r) >> 1;
    if (l <= mid)update(ls,l,r,val);
    if (mid < r)update(rs,l,r,val);
    pushup(rt);
}
inline ll query(int rt,int l,int r){
    if (l <= t[rt].l and t[rt].r <= r){
        t[rt].sum %= mod;
        return t[rt].sum;
    }
    pushdown(rt);
    int mid = (t[rt].l+t[rt].r) >> 1;
    ll ans = 0;
    if (l <= mid)ans += query(ls,l,r);
    if (mid < r)ans += query(rs,l,r);
    ans %= mod;
    return ans;
}
inline void range_add1(int x,int y,int val){
    val %= mod;
    while(top[x] != top[y]){
        if (d[top[x]] < d[top[y]])swap(x,y);
        update(1,id[top[x]],id[x],val);
        x = f[top[x]];
    }
    if (d[x] > d[y])swap(x,y);
    update(1,id[x],id[y],val);
}
inline ll range_ask1(int x,int y){
    ll ans = 0;
    while(top[x] != top[y]){
        if (d[top[x]] < d[top[y]])swap(x,y);
        ans += query(1,id[top[x]],id[x]);
        ans %= mod;
        x = f[top[x]];
    }
    if (d[x] > d[y])swap(x,y);
    ans += query(1,id[x],id[y]);
    ans %= mod;
    return ans;
}
inline void range_add2(int x,int val){
    val %= mod;
    update(1,id[x],id[x] + siz[x] - 1,val);
}
inline ll range_ask2(int x){
    ll ans = 0;
    ans += query(1,id[x],id[x] + siz[x] - 1);
    ans %= mod;
    return ans;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m >> r >> mod;
    for(int i = 1;i <= n;i++){
        cin >> a[i];
        a[i] %= mod;
    }
    for(int i = 1;i <= n - 1;i++){
        int u,v;
        cin >> u >> v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs1(r,0);
    dfs2(r,r);
    build(1,1,n);
    while(m--){
        int op;
        cin >> op;
        if (op == 1){
            int x,y,z;
            cin >> x >> y >> z;
            range_add1(x,y,z);
        }else if(op == 2){
            int x,y;
            cin >> x >> y;
            cout << range_ask1(x,y) << '\n';
        }else if(op == 3){
            int x,z;
            cin >> x >> z;
            range_add2(x,z);
        }else{
            int x;
            cin >> x;
            cout << range_ask2(x) << "\n";
        }
    }
    return 0;
}

KMP

#include<bits/stdc++.h>
using namespace std;
string s,t;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> s >> t;
	int n = s.size(),m = t.size();
	s = ' ' + s,t = ' ' + t;
	vector<int>nxt(m+1,0);
	for(int i = 2,j = 0;i <= m;i++){
		while(j > 0 and t[i] != t[j + 1])j = nxt[j];
		if (t[i] == t[j + 1])j++;
		nxt[i] = j;
	}
	for(int i = 1,j = 0;i <= n;i++){
		while(j > 0 and s[i] != t[j + 1])j = nxt[j];
		if (s[i] == t[j + 1])j++;
		if (j == m){
			cout << i - m + 1 << "\n";
		}
	}
	for(int i = 1;i < nxt.size();i++)cout << nxt[i] << " ";
	return 0;
}

AC 自动机

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n,trie[N][26],fail[N],val[N],idx;
inline void insert(string s){
	int len = s.size(),p = 0;
	for(int i = 0;i < len;i++){
		int c = s[i] - 'a';
		if (!trie[p][c])trie[p][c] = ++idx;
		p = trie[p][c];
	}
	val[p]++;
}
inline void build(){
	queue<int>q;
	for(int c = 0;c < 26;c++){
		if (trie[0][c]){
			fail[trie[0][c]] = 0;
			q.push(trie[0][c]);
		}
	}
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int c = 0;c < 26;c++){
			int v = trie[u][c];
			if (v){
				fail[v] = trie[fail[u]][c];
				q.push(v);
			}else{
				trie[u][c] = trie[fail[u]][c];
			}
		}
	}
}
inline int query(string s){
	int len = s.size(),p = 0,ans = 0;
	for(int i = 0;i < len;i++){
		p = trie[p][s[i]-'a'];
		for(int t = p;t and val[t] != -1;t = fail[t]){
			ans += val[t];
			val[t] = -1;
		}
	}
	return ans;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for(int i = 1;i <= n;i++){
		string s;
		cin >> s;
		insert(s);
	}
	build();
	string s;
	cin >> s;
	cout << query(s);
	return 0;
}
posted @ 2026-11-10 10:59  Emoji-happy  阅读(26)  评论(0)    收藏  举报