LCA
//exam:P3379 【模板】最近公共祖先(LCA)
#include <iostream>
#include <cstdio>
#include <vector>
#define int long long
using namespace std;
const int MAXN=5e5+5,MAXM=25;
void dfs(int,int);
int lca(int,int);
vector<int> g[MAXN];
int deep[MAXN];
int n,q,s;
signed main(){cin>>n>>q>>s;for(int i=1,u,v;i<n;i++){cin>>u>>v;g[u].push_back(v);g[v].push_back(u);}dfs(s,0);while(q--){int a,b;cin>>a>>b;cout<<lca(a,b)<<endl;}return 0;
}
int f[MAXN][MAXM];
void dfs(int u,int fa){f[u][0]=fa,deep[u]=deep[fa]+1;for(int i=1;i<=20;i++){f[u][i]=f[f[u][i-1]][i-1];}for(int i=0;i<g[u].size();i++){int v=g[u][i];if(v!=fa){dfs(v,u);}}
}
int lca(int u,int v){if(deep[u]<deep[v]){swap(u,v);}int l=deep[u]-deep[v];for(int i=0;i<=20;i++){if(l&(1<<i)){u=f[u][i];} }if(u==v){return u;}for(int i=20;i>=0;i--){if(f[u][i]!=f[v][i]){u=f[u][i],v=f[v][i];}}return f[u][0];
}
树状数组
//exam:T588519 树状数组 3 :区间修改,区间查询
#include <iostream>
#include <cstdio>
#define int long long
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int MAXN=1e6+5;
int query(int x);
void update(int x,int v);
int tree1[MAXN],tree2[MAXN];
int n,q;
signed main(){ios::sync_with_stdio(false);cin>>n>>q;for(int i=1,u;i<=n;i++){cin>>u;update(i,u);update(i+1,-u);}while(q--){int op,l,r,x;cin>>op>>l>>r;if(op==1){cin>>x;update(l,x);update(r+1,-x);}else{cout<<query(r)-query(l-1)<<endl;}}return 0;
}
int query(int x){int res=0,res1=0,t=x;while(x){res+=tree1[x];res1+=tree2[x];x-=lowbit(x);}return res*(t+1)-res1;
}
void update(int x,int v){int v1=x*v;while(x<=n){tree1[x]+=v;tree2[x]+=v1;x+=lowbit(x);}
}
线段树
加法
//exam:P3372 【模板】线段树 1
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
const int MAXN=1e5+5;
void build(int,int,int);
int query(int,int,int);
void update(int,int,int,int);
int a[MAXN];
int n,m;
signed main(){cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];}build(1,1,n);for(int i=1,op,x,y,k;i<=m;i++){cin>>op>>x>>y;if(op==1){cin>>k;update(1,x,y,k);} else{cout<<query(1,x,y)<<endl;}
// for(int i=1;i<=n;i++){
// cout<<query(1,i,i)<<" ";
// }
// cout<<endl;} return 0;
}
struct SegmentTree{int value,l,r,add;#define value(x) tree[x].value//节点权值 #define l(x) tree[x].l#define r(x) tree[x].r#define add(x) tree[x].add#define ltree(x) ((x)<<1)#define rtree(x) (((x)<<1)+1)#define treesize(x) (r(x)-l(x)+1)#define mid(x) ((l(x)+r(x))>>1)
}tree[MAXN*4];
void build(int root,int l,int r){l(root)=l,r(root)=r;if(l==r){value(root)=a[l];return ;}int mid=mid(root);build(ltree(root),l,mid);build(rtree(root),mid+1,r);value(root)=value(ltree(root))+value(rtree(root));return ;
}
void spread(int x){value(ltree(x))+=add(x)*treesize(ltree(x));value(rtree(x))+=add(x)*treesize(rtree(x));add(ltree(x))+=add(x);add(rtree(x))+=add(x);add(x)=0;
}
int query(int root,int l,int r){if(l<=l(root)&&r(root)<=r){return value(root);}spread(root);int mid=mid(root),res=0;if(mid>=l){res+=query(ltree(root),l,r);}if(mid<r){res+=query(rtree(root),l,r);}return res;
}
void update(int root,int l,int r,int x){if(l<=l(root)&&r(root)<=r){add(root)+=x;value(root)+=x*treesize(root);return ;}spread(root);int mid=mid(root);if(mid>=l){update(ltree(root),l,r,x);}if(mid<r){update(rtree(root),l,r,x);}value(root)=value(ltree(root))+value(rtree(root));
}
加法和乘法
//exam:P3373 【模板】线段树 2
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
const int MAXN=1e5+5;
void build(int,int,int);
int query(int,int,int);
void update1(int,int,int,int);
void update2(int,int,int,int);
int a[MAXN];
int n,m,P;
signed main(){ios::sync_with_stdio(false);cin>>n>>m>>P;for(int i=1;i<=n;i++){cin>>a[i];}build(1,1,n);for(int i=1,op,x,y,k;i<=m;i++){cin>>op>>x>>y;if(op==1){cin>>k;update2(1,x,y,k);} else if(op==2){cin>>k;update1(1,x,y,k);} else{cout<<query(1,x,y)<<endl;}
// cout<<"#";
// for(int i=1;i<=n;i++){
// cout<<query(1,i,i)<<" ";
// }
// cout<<endl;} return 0;
}
struct SegmentTree{int value,l,r,add,mul;#define value(x) tree[x].value//节点权值 #define l(x) tree[x].l#define r(x) tree[x].r#define add(x) tree[x].add#define mul(x) tree[x].mul#define ltree(x) ((x)<<1)#define rtree(x) (((x)<<1)+1)#define treesize(x) (r(x)-l(x)+1)#define mid(x) ((l(x)+r(x))>>1)
}tree[MAXN*4];
void build(int root,int l,int r){l(root)=l,r(root)=r,mul(root)=1;if(l==r){value(root)=a[l];return ;}int mid=mid(root);build(ltree(root),l,mid);build(rtree(root),mid+1,r);value(root)=value(ltree(root))+value(rtree(root));return ;
}
void spread(int x){value(ltree(x))=value(ltree(x))*mul(x)%P; value(rtree(x))=value(rtree(x))*mul(x)%P; value(ltree(x))=(value(ltree(x))+add(x)*treesize(ltree(x))%P)%P;value(rtree(x))=(value(rtree(x))+add(x)*treesize(rtree(x))%P)%P;add(ltree(x))=(add(ltree(x))*mul(x)%P+add(x))%P;add(rtree(x))=(add(rtree(x))*mul(x)%P+add(x))%P;mul(ltree(x))=mul(ltree(x))*mul(x)%P;mul(rtree(x))=mul(rtree(x))*mul(x)%P;add(x)=0,mul(x)=1;
}
int query(int root,int l,int r){if(l<=l(root)&&r(root)<=r){return value(root);}spread(root);int mid=mid(root),res=0;if(mid>=l){res=(res+query(ltree(root),l,r))%P;}if(mid<r){res=(res+query(rtree(root),l,r))%P;}return res;
}
void update1(int root,int l,int r,int x){if(l<=l(root)&&r(root)<=r){add(root)=(add(root)+x)%P;value(root)=(value(root)+x*treesize(root)%P)%P;return ;}spread(root);int mid=mid(root);if(mid>=l){update1(ltree(root),l,r,x);}if(mid<r){update1(rtree(root),l,r,x);}value(root)=(value(ltree(root))+value(rtree(root)))%P;
}
void update2(int root,int l,int r,int x){if(l<=l(root)&&r(root)<=r){add(root)=add(root)*x%P;mul(root)=mul(root)*x%P;value(root)=(value(root)*x%P)%P;return ;}spread(root);int mid=mid(root);if(mid>=l){update2(ltree(root),l,r,x);}if(mid<r){update2(rtree(root),l,r,x);}value(root)=(value(ltree(root))+value(rtree(root)))%P;
}
分块
//exam:243. 分块
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=5e5+5;
void init();
int query(int,int,int);
void update(int,int,int);
pair<int,int> a[MAXN];
int n,m;
int T;
signed main(){ios::sync_with_stdio(false);cin>>n;for(int i=1;i<=n;i++){int t;cin>>t;a[i]=make_pair(t,i);}init();for(int i=1;i<=n;i++){int op,l,r,x;cin>>op>>l>>r>>x;if(op==1){cout<<query(l,r,x*x)<<endl;}else{update(l,r,x);}}return 0;
}
int pos[MAXN],L[MAXN],R[MAXN],add[MAXN];
void init(){T=sqrt(n);for(int i=1;i<=T;i++){L[i]=(i-1)*T+1,R[i]=i*T;}if(R[T]<n){L[T+1]=R[T]+1,R[T+1]=n;T++;}for(int i=1;i<=T;i++){sort(a+L[i],a+1+R[i]);for(int j=L[i];j<=R[i];j++){pos[j]=i;}}
}
int query(int x,int y,int k){int l=pos[x],r=pos[y],ans=0;if(l==r){for(int i=L[l];i<=R[l];i++){if(a[i].second>=x&&a[i].second<=y&&a[i].first<k-add[l]){ans++;}}}else{for(int i=L[l];i<=R[l];i++){if(a[i].second>=x&&a[i].first<k-add[l]){ans++;}}for(int i=l+1;i<=r-1;i++){ans+=lower_bound(a+L[i],a+R[i]+1,make_pair(k-add[i],-INF))-a-L[i];}for(int i=L[r];i<=R[r];i++){if(a[i].second<=y&&a[i].first<k-add[r]){ans++;}}}return ans;
}
void update(int x,int y,int k){int l=pos[x],r=pos[y];if(l==r){for(int i=L[l];i<=R[l];i++){if(a[i].second>=x&&a[i].second<=y){a[i].first+=k;}}sort(a+L[l],a+R[l]+1);}else{for(int i=L[l];i<=R[l];i++){if(a[i].second>=x){a[i].first+=k;}}sort(a+L[l],a+R[l]+1);for(int i=l+1;i<=r-1;i++){add[i]+=k;}for(int i=L[r];i<=R[r];i++){if(a[i].second<=y){a[i].first+=k;}}sort(a+L[r],a+R[r]+1);}
}
A*算法
//exam:P2901 [USACO08MAR] Cow Jogging G
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define int long long
using namespace std;
struct node{int next,w;bool operator < (const node &nxt) const{if(w!=nxt.w){return w>nxt.w;}return next>nxt.next;}
};
const int MAXN=1005;
void build();//建立估算数组
void output();
vector<node> g[MAXN],g0[MAXN];
priority_queue<node> q;
int d[MAXN];//估算数组
int n,m,k;
signed main(){ios::sync_with_stdio(false);cin>>n>>m>>k;for(int i=1,u,v,w;i<=m;i++){cin>>u>>v>>w;g[u].push_back((node){v,w});g0[v].push_back((node){u,w});}build();q.push((node){n,d[n]});while(!q.empty()){node u=q.top();q.pop();
// cout<<u.next<<" "<<u.w-d[u.next]<<" "<<u.w<<endl;if(u.next==1){cout<<u.w<<endl;k--;if(k==0){break;}}for(int i=0;i<g[u.next].size();i++){node v=g[u.next][i];q.push((node){v.next,d[v.next]+u.w-d[u.next]+v.w});}}while(k){cout<<-1<<endl;k--;}return 0;
}
void add(int v,int w){if(d[v]>=w){d[v]=w;q.push((node){v,w});}
}
void build(){for(int i=1;i<=n;i++){d[i]=0x3f3f3f3f;}add(1,0);while(!q.empty()){node u=q.top();q.pop();if(d[u.next]<u.w){continue;}for(int i=0;i<g0[u.next].size();i++){node v=g0[u.next][i];add(v.next,u.w+v.w);}}
}
最小生成树
//exam:P3366 【模板】最小生成树
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#define int long long
using namespace std;
struct node{int v,w;
};
struct edge{int u,v,w;bool operator < (const edge &nxt) const{return w>nxt.w;}
};
const int MAXN=5e3+5;
int solve();
bool check();
priority_queue<edge> q;
vector<node> g[MAXN],a[MAXN];
int n,m,ans;
signed main(){ios::sync_with_stdio(false);cin>>n>>m;for(int i=1,u,v,w;i<=m;i++){cin>>u>>v>>w;g[u].push_back((node){v,w});g[v].push_back((node){u,w});q.push((edge){u,v,w});}ans=solve();if(!check()){cout<<"orz";}else{cout<<ans;}return 0;
}
bool book[MAXN];
void dfs(int cur){book[cur]=true;for(int i=0;i<a[cur].size();i++){node u=a[cur][i];if(!book[u.v]){dfs(u.v);}}
}
bool check(){dfs(1);for(int i=1;i<=n;i++){if(!book[i]){return false;}}return true;
}
int fa[MAXN];
void init(){for(int i=1;i<=n;i++){fa[i]=i;}
}
int find(int x){if(fa[x]==x){return x; } return fa[x]=find(fa[x]);
}
void unity(int x,int y){int a=find(x),b=find(y);if(a==b){return ;} fa[a]=b;
}
bool same(int x,int y){return find(x)==find(y);
}
int solve(){init();int ans=0;while(!q.empty()){edge u=q.top();q.pop();if(same(u.u,u.v)){continue;}unity(u.u,u.v);a[u.u].push_back((node){u.v,u.w});a[u.v].push_back((node){u.u,u.w});ans+=u.w;}return ans;
}
埃氏筛
//exam:P3383 【模板】线性筛素数
#include <iostream>
#include <cstdio>
#include <cmath>
//#define int long long
using namespace std;
const int MAXN=2e8+5;
bool book[MAXN];
int a[MAXN],b[MAXN];
int n,q,m;
signed main(){ios::sync_with_stdio(false);cin>>n>>q;for(int i=2;i<=n;i++){if(!book[i]){b[++m]=i;for(int j=i*2;j<=n;j+=i){book[j]=true;}}}for(int i=1;i<=q;i++){int x;cin>>x;cout<<b[x]<<endl;}return 0;
}
线性筛
//exam:P3383 【模板】线性筛素数(线性筛)
#include <iostream>
#include <cstdio>
#include <cmath>
//#define int long long
using namespace std;
const int MAXN=2e8+5;
bool book[MAXN];
int a[MAXN],b[MAXN];
int n,q,m;
signed main(){ios::sync_with_stdio(false);cin>>n>>q;for(int i=2;i<=n;i++){if(!book[i]){b[++m]=i;}for(int j=1;j<=m&&i*b[j]<=n;j++){book[i*b[j]]=true;if(i%b[j]==0){break;}}}for(int i=1;i<=q;i++){int x;cin>>x;cout<<b[x]<<endl;}return 0;
}
扩展欧几里得定理
//exam:P1082 [NOIP 2012 提高组] 同余方程
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
void exgcd(int a,int b,int &x,int &y);
int a,b,x,y;
signed main(){ios::sync_with_stdio(false);cin>>a>>b;exgcd(a,b,x,y);cout<<x<<" "<<y;return 0;
}
void exgcd(int a,int b,int &x,int &y){if(b==0){x=1,y=0;return ;}exgcd(b,a%b,x,y);int x1=x,y1=y;x=y1,y=(x1-a/b*y1);
}
费马小定理&错排计数
//exam:P4071 [SDOI2016] 排列计数
#include <iostream>
#include <cstdio>
#define int long long
#define endl '\n'
using namespace std;
const int P=1e9+7;
const int MAXN=1e6+5;
void build();
int solve(int,int);
int t,n,m;
signed main(){ios::sync_with_stdio(false);build();cin>>t;while(t--){cin>>n>>m;cout<<solve(n,m)<<endl;}return 0;
}
int f[MAXN],finv[MAXN],dp[MAXN];
int qpow(int x,int y){int res=1;while(y){if((y&1)==1){res=res*x%P;}y>>=1;x=x*x%P;}return res;
}
void build(){f[0]=finv[0]=1,dp[2]=1,dp[0]=1;for(int i=1;i<=1e6;i++){finv[i]=finv[i-1]*qpow(i,P-2)%P;//阶乘逆元f[i]=f[i-1]*i%P;if(i>=3){dp[i]=(i-1)*(dp[i-1]+dp[i-2])%P;}}
}
int C(int n,int m){return f[n]*finv[m]%P*finv[n-m]%P;
}
int solve(int n,int m){return C(n,m)*dp[n-m]%P;
}
字符串哈希
//exam:P10468 兔子与兔子
#include <iostream>
#include <cstdio>
#define int unsigned long long
using namespace std;
const int MAXN=1e6+5;
const int P=1331;
int hs(int,int);
string s;
int H[MAXN],PS[MAXN];
int n,x1,x2,y1,y2;
signed main(){ios::sync_with_stdio(false);cin>>s>>n;s=" "+s;PS[0]=1;for(int i=1;i<s.size();i++){H[i]=H[i-1]*P+s[i];PS[i]=PS[i-1]*P;}while(n--){cin>>x1>>y1>>x2>>y2;int h1=hs(x1,y1),h2=hs(x2,y2);if(h1==h2){cout<<"Yes\n";}else{cout<<"No\n";}}return 0;
}
int hs(int l,int r){return H[r]-H[l-1]*PS[r-l+1];
}
Trie
//exam:P10470 前缀统计
#include <iostream>
#include <cstring>
#include <cstdio>
#define int long long
#define endl '\n'
using namespace std;
const int MAXN=1e6+5;
const int MAXM=30;
struct trie{#define idx(c) ((c)-'a')int ch[MAXN][MAXM];//ch[i][j]表示节点,j表示边int val[MAXN];//记录当前节点的信息 int size;//节点数量 trie(){//构造函数 size=0;memset(ch[0],0,sizeof(ch[0]));}void insert(string s){int u=0;for(int i=0;i<s.size();i++){int t=idx(s[i]);if(ch[u][t]==0){size++;memset(ch[size],0,sizeof(ch[size]));ch[u][t]=size;}u=ch[u][t];}val[u]++;}int query(string s){int u=0,res=val[0];for(int i=0;i<s.size();i++){int t=idx(s[i]);if(ch[u][t]==0){break;}u=ch[u][t];res+=val[u];}return res;}
};
int n,m;
trie t;
signed main(){ios::sync_with_stdio(false);cin>>n>>m;for(int i=1;i<=n;i++){string s;cin>>s;t.insert(s);}for(int i=1;i<=m;i++){string s;cin>>s;cout<<t.query(s)<<endl;}return 0;
}
KMP
//exam:P3375 【模板】KMP
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
const int MAXN=1e6+5;
void getF(string);
int fail[MAXN];//失配
string s1,s2;
int cur;
signed main(){ios::sync_with_stdio(false);cin>>s2>>s1;//模式串,匹配串 getF(s1);for(int i=0;i<s2.size();i++){if(s1[cur]==s2[i]){cur++;}else{while(cur&&s2[i]!=s1[cur]){cur=fail[cur];}cur=(s2[i]==s1[cur]?(cur+1):0);}if(cur==s1.size()){cout<<i-s1.size()+2<<endl; cur=fail[cur];}}for(int i=1;i<=s1.size();i++){cout<<fail[i]<<" ";}return 0;
}
void getF(string s){fail[0]=fail[1]=0;int l=s.size();for(int i=1;i<l;i++){//从i状态算i+1 int cur=fail[i];//失配之后到达的状态while(cur&&s[cur]!=s[i]){//不断失配 cur=fail[cur];} fail[i+1]=(s[cur]==s[i]?(cur+1):0);}
}