模板代码
yi_hr
·
·
个人记录
模板整理
一. 数据结构
1.序列
ST 表
constexpr int N=1e6+9;
int n,m;
int a[N],s[N][30];
void build(){
for(int i=1;i<=n;i++){
s[i][0]=a[i];
}
int t=log(n)/log(2);
for(int j=1;j<=t;j++){
for(int i=1;i<=n-(1<<j)+1;i++){
s[i][j]=max(s[i][j-1],s[i+(1<<(j-1))][j-1]);
}
}
}
inline int query(int l,int r){
int t=log(r-l+1)/log(2);
return max(s[l][t],s[r-(1<<t)+1][t]);
}
树状数组
constexpr int N=1e6+9;
int t[N];
inline int lowbit(int x){return x&(-x);}
inline void update(int x,int val){
for(int i=x;i<=n;i+=lowbit(i)) t[i]+=val;
}
inline int query(int x){
int res=0;
for(int i=x;i;i-=lowbit(i)) res+=t[i];
return res;
}
字典树
constexpr int N=3e6+9;
int n,q,a[N];
int t[N][70],cnt[N],id;
inline int num(const char &x){
if(x>='A'&&x<='Z') return x-'A';
if(x>='a'&&x<='z') return x-'a'+26;
return x-'0'+52;
}
inline void insert(string &s){
int p=0;
for(auto i : s){
int x=num(i);
if(!t[p][x]) t[p][x]=++id;
p=t[p][x];
cnt[p]++;
}
}
inline int find(string &s){
int p=0;
for(auto i : s){
int x=num(i);
if(!t[p][x]) return 0;
p=t[p][x];
}
return cnt[p];
}
线段树
constexpr int N=1e6+9;
int n,m;
ll a[N];
struct tree{
ll sum,tag;
}t[N<<2];
#define mid ((l+r)>>1)
inline void f(int p,int len,ll k){
t[p].sum+=k*len;
t[p].tag+=k;
}
inline void push_up(int p){
t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
}
inline void push_down(int p,int l,int r){
f(p<<1,mid-l+1,t[p].tag);
f(p<<1|1,r-mid,t[p].tag);
t[p].tag=0;
}
void build(int p,int l,int r){
if(l==r){
t[p].sum=a[l];
return ;
}
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
push_up(p);
}
void update(int p,int l,int r,int li,int ri,ll x){
if(li<=l&&ri>=r){
f(p,r-l+1,x);
return ;
}
push_down(p,l,r);
if(li<=mid){
update(p<<1,l,mid,li,ri,x);
}
if(ri>mid){
update(p<<1|1,mid+1,r,li,ri,x);
}
push_up(p);
}
ll query(int p,int l,int r,int li,int ri){
if(li<=l&&ri>=r){
return t[p].sum;
}
push_down(p,l,r);
ll res=0;
if(li<=mid){
res+=query(p<<1,l,mid,li,ri);
}
if(ri>mid){
res+=query(p<<1|1,mid+1,r,li,ri);
}
push_up(p);
return res;
}
#undef mid
离线二维数点
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=2e6+9;
int n,m,a[N];
struct node{
int x,val;
int id;
};
int t[N];
inline int lowbit(int x){ return x&(-x);}
inline void update(int x){
for(int i=x;i<N;i+=lowbit(i)){
t[i]++;
}
}
inline int query(int x){
int res=0;
for(int i=x;i>=1;i-=lowbit(i)){
res+=t[i];
}
return res;
}
int ans[N],opt;
vector<node> b[N];
inline void insert(int id,int x,int y,int val){
b[x].push_back({y,val,id});
}
void count_point(){
for(int i=1;i<=n;i++){
update(a[i]);
for(auto j : b[i]){
ans[j.id]+=j.val*query(j.x);
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int l,r,x;
for(int i=1;i<=m;i++){
cin>>l>>r>>x;
opt++;
insert(opt,r,x,1);
insert(opt,l-1,x,-1);
}
count_point();
for(int i=1;i<=m;i++){
cout<<ans[i]<<"\n";
}
return 0;
}
平衡树
笛卡尔树
可持久化线段树
动态开点线段树
可分裂/合并线段树
莫队
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
int n,m,k,a[N],pos[N];
struct node{
int l,r,id;
bool operator <(const node &x)const{
return (pos[l]^pos[x.l])?(l<x.l):((pos[l]&1)?r<x.r:r>x.r);
}
}b[N];
ll ans[N],cnt[N];
ll res;
inline void add(int p){
//
}
inline void del(int p){
//
}
void solve(){
for(int i=1,l=1,r=0;i<=m;i++){
for(;r<b[i].r;r++) add(r+1);
for(;r>b[i].r;r--) del(r);
for(;l<b[i].l;l++) del(l);
for(;l>b[i].l;l--) add(l-1);
ans[b[i].id]=res;
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]^=a[i-1];
}
int block=n/sqrt(m*2/3);
for(int i=1;i<=n;i++){
pos[i]=(i-1)/block+1;
}
for(int i=1;i<=m;i++){
cin>>b[i].l>>b[i].r;
b[i].id=i;
}
sort(b+1,b+1+m);
solve();
for(int i=1;i<=m;i++){
cout<<ans[i]<<"\n";
}
return 0;
}
可持久化字典树
树套树
颜色段均摊/珂朵莉树
2.树形结构
点分治
树链剖分
#include<bits/stdc++.h>
#define bug puts("I will go to Peking University with tsq")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
struct edge{
int next,to;
}e[N];
int head[N],cnt;
inline void add(int u,int v){
e[++cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int n,m,r,mod,a[N];
// ds
int fa[N],d[N],sz[N],son[N],top[N],dfn[N],idx;
int ri[N];
void dfs1(int u){
sz[u]=1;d[u]=d[fa[u]]+1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa[u]) continue;
fa[v]=u;
dfs1(v);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]){
son[u]=v;
}
}
}
void dfs2(int u,int tp){
dfn[u]=++idx;
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
ri[u]=idx;
}
void path_update(int u,int v,int val){
while(top[u]!=top[v]){
if(d[top[u]]<d[top[v]]) swap(u,v);
update(1,1,n,dfn[top[u]],dfn[u],val);
u=fa[top[u]];
}
if(d[u]>d[v]) swap(u,v);
update(1,1,n,dfn[u],dfn[v],val);
}
void tree_update(int u,int val){
update(1,1,n,dfn[u],ri[u],val);
}
int path_query(int u,int v){
int res=0;
while(top[u]!=top[v]){
if(d[top[u]]<d[top[v]]) swap(u,v);
res+=query(1,1,n,dfn[top[u]],dfn[u]);
res%=mod;
u=fa[top[u]];
}
if(d[u]>d[v]) swap(u,v);
res+=query(1,1,n,dfn[u],dfn[v]);
res%=mod;
return res;
}
int tree_query(int u){
return query(1,1,n,dfn[u],ri[u]);
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m>>r>>mod;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int u,v;
for(int i=1;i<n;i++){
cin>>u>>v;
add(u,v);
add(v,u);
}
fa[r]=r;
dfs1(r);
dfs2(r,r);
for(int i=1;i<=n;i++){
update(1,1,n,dfn[i],dfn[i],a[i]);
}
while(m--){
int op,x,y,z;
cin>>op;
if(op==1){
cin>>x>>y>>z;
path_update(x,y,z);
}else if(op==2){
cin>>x>>y;
cout<<path_query(x,y)<<'\n';
}else if(op==3){
cin>>x>>z;
tree_update(x,z);
}else{
cin>>x;
cout<<tree_query(x)<<'\n';
}
}
return 0;
}
dsu on tree
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
struct edge{
int next,to;
}e[N];
int head[N],cnt;
inline void add(int u,int v){
e[++cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int n,m,a[N];
int son[N],sz[N];
void dfs1(int u,int fa){
sz[u]=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa) continue;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]){
son[u]=v;
}
}
}
ll ans[N],opt[N];
ll maxx,sum;
void dfs2(int u,int fa,int p){
opt[a[u]]++;
if(opt[a[u]]==maxx){
sum+=a[u];
}
if(opt[a[u]]>maxx){
sum=a[u];
maxx=opt[a[u]];
}
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa||v==p) continue;
dfs2(v,u,p);
}
}
void del(int u,int fa){
opt[a[u]]--;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa) continue;
del(v,u);
}
}
void dfs(int u,int fa){
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa||v==son[u]) continue;
dfs(v,u);
del(v,u);
maxx=sum=0;
}
if(son[u]){
dfs(son[u],u);
}
dfs2(u,fa,son[u]);
ans[u]=sum;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int u,v;
for(int i=1;i<n;i++){
cin>>u>>v;
add(u,v);
add(v,u);
}
dfs1(1,1);
dfs(1,1);
for(int i=1;i<=n;i++){
cout<<ans[i]<<" ";
}
return 0;
}
二. 数学
1.数论
线性筛素数
int n,p[N];
bitset<N> vis;
void init(){
int cnt=0;
for(int i=2;i<=n;i++){
if(!vis[i]) p[++cnt]=i;
for(int j=1;j<=cnt&&(i*p[j]<=n);j++){
vis[i*p[j]]=1;
if(i%p[j]){
continue;
}
break;
}
}
}
逆元
struct INV{
inline ll qpow(ll x,ll b,ll mod){
ll res=1;
for(;b;b>>=1,x*=x,x%=mod){
if(b&1) res*=x,res%=mod;
}
return res;
}
inline int inv(int x,int p){
return qpow(x,p-2,p);
}
}inv;
中国剩余定理
struct CRT{
void exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1;
y=0;
return ;
}
exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
inline ll inv(ll x,ll p){
ll a=0,b=0;
exgcd(x,p,a,b);
return (a%p+p)%p;
}
inline ll crt(int n,ll *a,ll *b){
ll m=1,x=0;
for(int i=1;i<=n;i++){
m*=a[i];
}
for(int i=1;i<=n;i++){
__int128 mi=m/a[i],t=inv(mi,a[i]);
x+=mi*t*b[i]%m;
x%=m;
}
return x;
}
}crt;
欧拉函数
int n,p[N],phi[N];
bitset<N> vis;
void init(){
int cnt=0;
phi[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]) p[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&(i*p[j]<=n);j++){
vis[i*p[j]]=1;
if(i%p[j]){
phi[i*p[j]]=phi[i]*phi[p[j]];
continue;
}
phi[i*p[j]]=phi[i]*p[j];
break;
}
}
}
卢卡斯定理
原根
BSGS
constexpr int N=1e6+9;
inline ll qpow(ll x,ll b,ll mod){
ll res=1;
while(b){
if(b&1){
res*=x;
res%=mod;
}
x*=x;
x%=mod;
b>>=1;
}
return res;
}
ll BSGS(ll x,ll y,ll mod){
x%=mod;
y%=mod;
ll m=ceil(sqrt(mod));
unordered_map<ll,ll> ma;
ll num=1;
for(int i=0;i<=m;i++){
ma[(y*num)%mod]=i;
num*=x;
num%=mod;
}
num=1;
ll am=qpow(x,m,mod);
for(int i=1;i<=m;i++){
num*=am;
num%=mod;
if(ma.find(num)!=ma.end()){
return i*m-ma[num];
}
}
return -1;
}
exBGSG
类欧几里得算法
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9,mod=998244353;
ll inv2=499122177,inv6=166374059;
struct node{
node(){f=g=h=0;}
ll f,g,h;
};
node f(ll a,ll b,ll c,ll n){
ll m=(a*n+b)/c;
node d;
if(a==0){
d.f=b/c*(n+1)%mod;
d.g=b/c*n%mod*(n+1)%mod*inv2%mod;
d.h=b/c*(b/c)%mod*(n+1)%mod;
return d;
}
if(a>=c||b>=c){
d.f=n*(n+1)%mod*inv2%mod*(a/c)%mod+b/c*(n+1)%mod;
d.g=a/c*n%mod*(n+1)%mod*(n*2+1)%mod*inv6%mod+b/c*n%mod*(n+1)%mod*inv2%mod;
d.h=a/c*(a/c)%mod*n%mod*(n+1)%mod*(n*2+1)%mod*inv6%mod+b/c*(b/c)%mod*(n+1)%mod+a/c*(b/c)%mod*n%mod*(n+1)%mod;
d.f%=mod,d.g%=mod,d.h%=mod;
node t=f(a%c,b%c,c,n);
d.h+=t.h+2*(b/c)%mod*t.f%mod+2*(a/c)%mod*t.g%mod;
d.g+=t.g,d.f+=t.f;
d.f%=mod,d.g%=mod,d.h%=mod;
return d;
}else{
node t=f(c,c-b-1,a,m-1);
d.f=n*m%mod-t.f;
d.f=(d.f%mod+mod)%mod;
d.g=n*m%mod*(n+1)%mod-t.h-t.f;
d.g=(d.g*inv2%mod+mod)%mod;
d.h=n*m%mod*(m+1)%mod-2*t.g-2*t.f-d.f;
d.h=(d.h%mod+mod)%mod;
return d;
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--){
ll n,a,b,c;
cin>>n>>a>>b>>c;
node ans=f(a,b,c,n);
cout<<ans.f<<' '<<ans.h<<' '<<ans.g<<'\n';
}
return 0;
}
2.多项式与生成函数
FFT
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr double pi=acos(-1.0);
constexpr int N=5e6+9;
struct cp{
double a,b;
cp(double x=0,double y=0){a=x,b=y;}
}a[N],b[N];
cp operator + (const cp &a,const cp &b){ return {a.a+b.a,a.b+b.b};}
cp operator - (const cp &a,const cp &b){ return {a.a-b.a,a.b-b.b};}
cp operator * (const cp &a,const cp &b){ return {a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a};}
int r[N];
void FFT(int len,cp *a,int t){
for(int i=0;i<len;i++){
if(i<r[i]) swap(a[i],a[r[i]]);
}
for(int i=1;i<len;i<<=1){
cp wn={cos(pi/i),t*sin(pi/i)};
for(int j=0;j<len;j+=(i<<1)){
cp w={1,0};
for(int k=0;k<i;k++,w=w*wn){
cp x=a[j+k],y=w*a[i+j+k];
a[j+k]=x+y;
a[i+j+k]=x-y;
}
}
}
}
int n,m,len,l;
void init(){
len=1,l=0;
while(len<=n+m) len<<=1,l++;
for(int i=0;i<len;i++){
r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
}
FFT(len,a,1);
FFT(len,b,1);
for(int i=0;i<=len;i++){
a[i]=a[i]*b[i];
}
FFT(len,a,-1);
}
void print(){
for(int i=0;i<=n+m;i++){
cout<<(int)(a[i].a/len+0.5)<<" ";
}
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
for(int i=0;i<=n;i++){
cin>>a[i].a;
}
for(int i=0;i<=m;i++){
cin>>b[i].a;
}
init();
print();
return 0;
}
NTT
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=5e6+9,mod=998244353;
inline ll qpow(ll x,ll b,ll mod){
ll res=1;
for(;b;b>>=1,x*=x,x%=mod){
if(b&1) res*=x,res%=mod;
}
return res;
}
int r[N],g=3,gi=qpow(3,mod-2,mod);
void NTT(int len,ll *a,int t){
for(int i=0;i<len;i++){
if(i<r[i]) swap(a[i],a[r[i]]);
}
for(int i=1;i<len;i<<=1){
ll wn=qpow(t==1?g:gi,(mod-1)/(i<<1),mod);
for(int j=0;j<len;j+=(i<<1)){
ll w=1;
for(int k=0;k<i;k++,w=w*wn%mod){
int x=a[j+k],y=w*a[i+j+k]%mod;
a[j+k]=(x+y)%mod;
a[i+j+k]=(x-y+mod)%mod;
}
}
}
}
int len,l;
ll n,m,a[N],b[N];
void init(){
len=1,l=0;
while(len<=n+m) len<<=1,l++;
for(int i=0;i<len;i++){
r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
}
NTT(len,a,1);
NTT(len,b,1);
for(int i=0;i<len;i++){
a[i]=a[i]*b[i]%mod;
}
NTT(len,a,-1);
}
void print(){
ll inv=qpow(len,mod-2,mod);
for(int i=0;i<=n+m;i++)
cout<<(a[i]*inv)%mod<<" ";
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
for(int i=0;i<=n;i++){
cin>>a[i];
}
for(int i=0;i<=m;i++){
cin>>b[i];
}
init();
print();
return 0;
}
FWT
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9,mod=998244353;
inline int qpow(ll x,int b){
ll res=1;
while(b){
if(b&1){
res*=x,res%=mod;
}
x*=x,x%=mod;
b>>=1;
}
return res;
}
void FWT_or(int len,ll *a,int t){
for(int i=2;i<=len;i<<=1){
int mid=i>>1;
for(int j=0;j<len;j+=i){
for(int k=0;k<mid;k++){
a[j+k+mid]+=a[j+k]*t+mod;
a[j+k+mid]%=mod;
}
}
}
}
void FWT_and(int len,ll *a,int t){
for(int i=2;i<=len;i<<=1){
int mid=i>>1;
for(int j=0;j<len;j+=i){
for(int k=0;k<mid;k++){
a[j+k]+=a[j+k+mid]*t+mod;
a[j+k]%=mod;
}
}
}
}
void FWT_xor(int len,ll *a,int t){
for(int i=2;i<=len;i<<=1){
int mid=i>>1;
for(int j=0;j<len;j+=i){
for(int k=0;k<mid;k++){
ll a1=a[j+k],a2=a[j+k+mid];
a[j+k]=(a1+a2)*t%mod;
a[j+k+mid]=(a1-a2+mod)*t%mod;
}
}
}
}
int n,m;
ll a[N],b[N];
ll ai[N],bi[N];
void print(){
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
cout<<"\n";
}
void get_or(){
for(int i=0;i<n;i++) a[i]=ai[i];
for(int i=0;i<n;i++) b[i]=bi[i];
FWT_or(n,a,1);
FWT_or(n,b,1);
for(int i=0;i<n;i++){
a[i]=a[i]*b[i]%mod;
}
FWT_or(n,a,-1);
print();
}
void get_and(){
for(int i=0;i<n;i++) a[i]=ai[i];
for(int i=0;i<n;i++) b[i]=bi[i];
FWT_and(n,a,1);
FWT_and(n,b,1);
for(int i=0;i<n;i++){
a[i]=a[i]*b[i]%mod;
}
FWT_and(n,a,-1);
print();
}
void get_xor(){
for(int i=0;i<n;i++) a[i]=ai[i];
for(int i=0;i<n;i++) b[i]=bi[i];
FWT_xor(n,a,1);
FWT_xor(n,b,1);
for(int i=0;i<n;i++){
a[i]=a[i]*b[i]%mod;
}
FWT_xor(n,a,qpow(2,mod-2));
print();
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n;
n=(1<<n);
for(int i=0;i<n;i++){
cin>>ai[i];
}
for(int i=0;i<n;i++){
cin>>bi[i];
}
get_or();
get_and();
get_xor();
return 0;
}
子集卷积
#include<bits/stdc++.h>
#define ppc __builtin_popcount
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=2e6+9,mod=1e9+9;
void FWT_or(int len,ll *a,int t){
for(int i=2;i<=len;i<<=1){
int mid=i>>1;
for(int j=0;j<len;j+=i){
for(int k=0;k<mid;k++){
a[j+k+mid]+=a[j+k]*t+mod;
a[j+k+mid]%=mod;
}
}
}
}
ll n,m,a[N],b[N];
ll ai[25][N],bi[25][N];
ll ci[45][N];
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n;m=n;
n=(1<<n);
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n;i++){
cin>>b[i];
}
for(int i=0;i<n;i++){
ai[ppc(i)][i]=a[i];
bi[ppc(i)][i]=b[i];
}
for(int i=0;i<=m;i++){
FWT_or(n,ai[i],1);
FWT_or(n,bi[i],1);
}
for(int i=0;i<=m;i++){
for(int j=0;j<=i;j++){
for(int k=0;k<n;k++){
ci[i][k]+=ai[j][k]*bi[i-j][k];
ci[i][k]%=mod;
}
}
}
for(int i=0;i<=m;i++){
FWT_or(n,ci[i],-1);
}
for(int i=0;i<n;i++){
cout<<ci[ppc(i)][i]<<" ";
}
return 0;
}
Dirichlet 卷积
3.线性代数
矩阵乘法
矩阵快速幂
行列式求值
矩阵树
4.其他
快速幂
inline ll qpow(ll x,ll b){
ll res=1;
while(b){
if(b&1){
res*=x,res%=mod;
}
x*=x,x%=mod;
b>>=1;
}
return res;
}
高精度
FFT 高精乘
constexpr double pi=acos(-1.0);
constexpr int N=5e6+9;
struct cp{
double a,b;
cp(double x=0,double y=0){a=x,b=y;}
}a[N],b[N];
cp operator + (const cp &a,const cp &b){ return {a.a+b.a,a.b+b.b};}
cp operator - (const cp &a,const cp &b){ return {a.a-b.a,a.b-b.b};}
cp operator * (const cp &a,const cp &b){ return {a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a};}
int r[N];
void FFT(int len,cp *a,int t){
for(int i=0;i<len;i++){
if(i<r[i]) swap(a[i],a[r[i]]);
}
for(int i=1;i<len;i<<=1){
cp wn={cos(pi/i),t*sin(pi/i)};
for(int j=0;j<len;j+=(i<<1)){
cp w={1,0};
for(int k=0;k<i;k++,w=w*wn){
cp x=a[j+k],y=w*a[i+j+k];
a[j+k]=x+y;
a[i+j+k]=x-y;
}
}
}
}
int n,m,len,l;
void init(){
len=1,l=0;
while(len<=n+m) len<<=1,l++;
for(int i=0;i<len;i++){
r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
}
FFT(len,a,1);
FFT(len,b,1);
for(int i=0;i<=len;i++){
a[i]=a[i]*b[i];
}
FFT(len,a,-1);
}
int ans[N];
void cheng(string &s1,string &s2){
n=s1.size()-1;
m=s2.size()-1;
for(int i=0;i<=n;i++){
a[i].a=s1[n-i]-'0';
}
for(int i=0;i<=m;i++){
b[i].a=s2[m-i]-'0';
}
init();
}
void print(){
for(int i=0;i<=len;i++){
ans[i]+=a[i].a/len+0.5;
if(ans[i]>=10){
ans[i+1]+=ans[i]/10;
ans[i]%=10;
}
}
bool flag=1;
for(int i=len;i>=0;i--){
if(flag&&ans[i]==0) continue;
flag=0;
cout<<ans[i];
}
}
复数类
康托展开
三. 图论
1.图
存图
有边权
struct edge{
int next,to,w;
}e[N];
int head[N],cnt;
inline void add(int u,int v,int w){
e[++cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
无边权
struct edge{
int next,to;
}e[N];
int head[N],cnt;
inline void add(int u,int v){
e[++cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
拓扑排序
struct TP{
int tp[N],idx=0,in[N];
void tp_sort(){
queue<int> q;
for(int i=1;i<=n;i++){
if(!in[i]){
q.push(i);
}
}
while(!q.empty()){
int u=q.front();q.pop();
tp[++idx]=u;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(--a[v]==0){
q.push(v);
}
}
}
}
}tp;
单源最短路
SPFA
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
struct edge{
int next,to,w;
}e[N];
int head[N],cnt;
inline void add(int u,int v,int w){
e[++cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
int n,m,s,dis[N];
bitset<N> vis;
void spfa(){
queue<int> q;
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
q.push(s);
vis[s]=1;
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(vis[v]) continue;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
q.push(v);
}
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m>>s;
int u,v,w;
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
add(u,v,w);
}
spfa();
for(int i=1;i<=n;i++){
cout<<(dis[i]==INF?((1<<31)-1):dis[i])<<" ";
}
return 0;
}
dijkstra
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
struct edge{
int next,to,w;
}e[N];
int head[N],cnt;
inline void add(int u,int v,int w){
e[++cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
int n,m,s,dis[N];
struct node{
int u,dis;
bool operator <(const node &x)const{
return dis>x.dis;
}
};
void dij(){
priority_queue<node> q;
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
q.push({s,0});
while(!q.empty()){
int u=q.top().u;
q.pop();
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(dis[u]+e[i].w<dis[v]){
dis[v]=dis[u]+e[i].w;
q.push({v,dis[v]});
}
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m>>s;
int u,v,w;
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
add(u,v,w);
}
dij();
for(int i=1;i<=n;i++){
cout<<(dis[i]==INF?((1<<31)-1):dis[i])<<" ";
}
return 0;
}
多源最短路
Floyd
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e2+9;
int n,m,a[N][N];
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
memset(a,0x3f,sizeof(a));
for(int i=1;i<=n;i++){
a[i][i]=0;
}
int u,v,w;
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
a[u][v]=a[v][u]=min(a[u][v],w);
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<a[i][j]<<" ";
}
cout<<"\n";
}
return 0;
}
johnson
负环
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e4+9;
struct edge{
int next,to,w;
}e[N];
int head[N],cnt;
inline void add(int u,int v,int w){
e[++cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
ll n,m,s,dis[N];
int opt[N];
bitset<N> vis;
void spfa(){
memset(dis,0x3f,sizeof(dis));
memset(opt,0,sizeof(opt));
vis.reset();
queue<int> q;
dis[1]=0;
q.push(1);
vis[1]=1;
while(!q.empty()){
int u=q.front();q.pop();
if(++opt[u]>n+1){
cout<<"YES\n";
return ;
}
vis[u]=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(vis[v]) continue;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
q.push(v);
}
}
}
cout<<"NO\n";
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--){
memset(head,0,sizeof(head));
cnt=0;
cin>>n>>m;
int u,v,w;
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
if(w>=0){
add(u,v,w);
add(v,u,w);
}else{
add(u,v,w);
}
}
spfa();
}
return 0;
}
最小生成树
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
int n,m,f[N];
inline int find(int u){
return (u==f[u]?u:f[u]=find(f[u]));
}
struct node{
int u,v,w;
bool operator <(const node &x)const{
return x.w>w;
}
}a[N];
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) f[i]=i;
int u,v,w;
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
a[i]={u,v,w};
}
sort(a+1,a+1+m);
int ans=0;
for(int i=1;i<=m;i++){
int fu=find(a[i].u),fv=find(a[i].v);
if(fu==fv) continue;
ans+=a[i].w;
f[fv]=fu;
}
int fo=find(1);
for(int i=2;i<=n;i++){
if(find(i)!=fo){
cout<<"orz";
return 0;
}
}
cout<<ans;
return 0;
}
强连通分量
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
struct edge{
int next,to;
}e[N<<1];
int head[N],cnt;
inline void add(int u,int v){
e[++cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int n,m;
int dfn[N],low[N],idx,opt,be[N];
stack<int> s;
bitset<N> ins;
void tarjan(int u){
dfn[u]=low[u]=++idx;
ins[u]=1;
s.push(u);
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else{
if(ins[v]) low[u]=min(low[u],low[v]);
}
}
if(low[u]==dfn[u]){
++opt;
while(1){
int v=s.top();s.pop();
ins[v]=0;
if(v==u) break;
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
int u,v;
for(int i=1;i<=m;i++){
cin>>u>>v;
add(u,v);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i);
}
//
return 0;
}
边双连通分量
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
struct edge{
int next,to;
}e[N<<2];
int head[N],cnt=1;
inline void add(int u,int v){
e[++cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int n,m;
int dfn[N],low[N],idx,opt;
bitset<N> ins;
stack<int> s;
void tarjan(int u,int fa){
dfn[u]=low[u]=++idx;
ins[u]=1;
s.push(u);
for(int i=head[u];i;i=e[i].next){
if((i>>1)==(fa>>1)) continue;
int v=e[i].to;
if(!dfn[v]){
tarjan(v,i);
low[u]=min(low[u],low[v]);
}else{
if(ins[v]) low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
++opt;
vector<int> p;
while(1){
int v=s.top();s.pop();
ins[v]=0;
if(v==u)break;
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
int u,v;
for(int i=1;i<=m;i++){
cin>>u>>v;
add(u,v);
add(v,u);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i,-1);
}
//
return 0;
}
点双连通分量
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
struct edge{
int next,to;
}e[N<<2];
int head[N],cnt=1;
inline void add(int u,int v){
e[++cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int n,m;
int dfn[N],low[N],idx,opt;
stack<int> s;
vector<vector<int>> a;
void tarjan(int u,int la){
dfn[u]=low[u]=++idx;
s.push(u);
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==la) continue;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]){
++opt;
vector<int> p;
while(1){
int x=s.top();s.pop();
p.push_back(x);
if(x==v) break;
}
p.push_back(u);
a.push_back(p);
}
}else{
low[u]=min(low[u],dfn[v]);
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
int u,v;
for(int i=1;i<=m;i++){
cin>>u>>v;
if(u==v) continue;
add(u,v);
add(v,u);
}
for(int i=1;i<=n;i++){
if(!dfn[i]&&head[i]) tarjan(i,i);
if(!dfn[i]&&!head[i]){
opt++;
a.push_back(vector<int>{i});
}
}
//
return 0;
}
割点
欧拉路径
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll long long
using namespace std;
const int N=1e5+9;
struct edge{
int next,to;
}e[N<<2];
int head[N],cnt=1;
inline void add(int u,int v){
e[++cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int n,m,a[N];
int now[N],in[N],out[N];
bitset<N<<2> vis;
void sort_edge(){
vector<int> vec;
for(int i=1;i<=n;i++){
vec.clear();
int op=0;
now[i]=head[i];
for(int j=head[i];j;j=e[j].next){
vec.push_back(e[j].to);
}
sort(vec.begin(),vec.end());
for(int j=head[i];j;j=e[j].next){
e[j].to=vec[op++];
}
}
}
stack<int> s;
void dfs(int u){
for(int i=now[u];i;i=now[u]){
now[u]=e[i].next;
dfs(e[i].to);
}
s.push(u);
}
void solve(){
int cnt_s=0,cnt_t=0,S=1;
bool flag=1;
for(int i=1;i<=n;i++){
if(in[i]!=out[i]){
flag=0;
if(in[i]+1==out[i]){
if(cnt_s){
cout<<"No";exit(0);
}
cnt_s=1;
S=i;
}
else if(out[i]+1==in[i]){
if(cnt_t){
cout<<"No";exit(0);
}
cnt_t=1;
}else{
cout<<"No";exit(0);
}
}
}
if((!flag)&&!(cnt_t==1&&cnt_s==1)){
cout<<"No";exit(0);
}
dfs(S);
while(!s.empty()){
cout<<s.top()<<" ";
s.pop();
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
int u,v;
for(int i=1;i<=m;i++){
cin>>u>>v;
in[v]++ ;
out[u]++;
add(u,v);
}
sort_edge();
solve();
return 0;
}
二分图最大匹配
差分约束
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
struct edge{
int next,to,w;
}e[N];
int head[N],cnt;
inline void add(int u,int v,int w){
e[++cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
int n,m,dis[N],opt[N];
bitset<N> vis;
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
int u,v,w;
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
add(u,v,-w);
}
for(int i=1;i<=n;i++){
add(0,i,0);
}
// memset(dis,0x3f,sizeof(dis));
memset(dis,128,sizeof(dis));
queue<int> q;
q.push(0);
dis[0]=0;
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=0;
if(++opt[u]>n){
cout<<"NO";return 0;
}
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(dis[u]+e[i].w>dis[v]){
dis[v]=dis[u]+e[i].w;
if(!vis[v]){
q.push(v);
vis[v]=1;
}
}
}
}
for(int i=1;i<=n;i++){
cout<<dis[i]<<' ';
}
return 0;
}
/*
u + w <= v
a - w <= b
*/
2-SAT
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=2e6+9;
struct edge{
int next,to;
}e[N<<1];
int head[N],cnt;
inline void add(int u,int v){
e[++cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int n,m;
int dfn[N],low[N],idx,opt,be[N];
stack<int> s;
bitset<N> ins;
void tarjan(int u){
dfn[u]=low[u]=++idx;
ins[u]=1;
s.push(u);
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else{
if(ins[v]) low[u]=min(low[u],low[v]);
}
}
if(low[u]==dfn[u]){
++opt;
while(1){
int v=s.top();s.pop();
ins[v]=0;
be[v]=opt;
if(v==u) break;
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
int u,v,a,b;
for(int i=1;i<=m;i++){
cin>>u>>a>>v>>b;
u--;v--;
u=(u<<1)+(a==1);
v=(v<<1)+(b==1);
add(u^1,v);
add(v^1,u);
}
for(int i=0;i<(n<<1);i++){
if(!dfn[i]) tarjan(i);
}
for(int i=0;i<n;i++){
if(be[i<<1]==be[i<<1|1]){
cout<<"IMPOSSIBLE";
return 0;
}
}
cout<<"POSSIBLE\n";
for(int i=0;i<n;i++){
if(be[i<<1]>be[i<<1|1]){
cout<<1<<" ";
}else{
cout<<0<<" ";
}
}
return 0;
}
最大流
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e5+9;
struct edge{
int next,to;
ll w;
}e[N];
int head[N],cnt=1;
inline void add(int u,int v,ll w){
e[++cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
int n,m,s,t;
ll maxflow;
int d[N],now[N];
bool bfs(){
memset(d,0,sizeof(d));
queue<int> q;
q.push(s);d[s]=1;
now[s]=head[s];
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(e[i].w&&!d[v]){
q.push(v);d[v]=d[u]+1;
now[v]=head[v];
if(v==t) return 1;
}
}
}
return 0;
}
ll dinic(int u,ll flow){
if(u==t) return flow;
ll rest=flow;
for(int i=now[u];i&&rest;i=e[i].next){
now[u]=i;
int v=e[i].to;
if(e[i].w&&d[u]+1==d[v]){
ll k=dinic(v,min(e[i].w,rest));
if(!k)d[v]=0;
e[i].w-=k;
e[i^1].w+=k;
rest-=k;
}
}
return flow-rest;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m>>s>>t;
int u,v;
ll w;
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
add(u,v,w);
add(v,u,0);
}
ll flow;
while(bfs()){
while(flow=dinic(s,INF)){
maxflow+=flow;
}
}
cout<<maxflow;
return 0;
}
费用流
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll int
using namespace std;
const int N=5e3+9,M=5e4+9;
struct edge{
int next,to;
ll w,c;
}e[M<<1];
int head[N],cnt=1;
inline void add(int u,int v,int w,int c){
e[++cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
e[cnt].c=c;
head[u]=cnt;
}
int n,m,s,t,a[N];
int pre[N];
ll dis[N],incf[N];
bitset<N> vis;
bool spfa(){
queue<int> q;
memset(dis,0x3f,sizeof(dis));
vis=0;
q.push(s);
dis[s]=0;
vis[s]=1;
incf[s]=LINF;
int u,v;
while(!q.empty()){
u=q.front();q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].next){
if(!e[i].w)continue;
v=e[i].to;
if(dis[v]>dis[u]+e[i].c){
dis[v]=dis[u]+e[i].c;
incf[v]=min(incf[u],e[i].w);
pre[v]=i;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
if(dis[t]==INF){
return 0;
}else{
return 1;
}
}
ll maxflow,mincost;
void update(){
int x=t;
while(x!=s){
int i=pre[x];
e[i].w-=incf[t];
e[i^1].w+=incf[t];
x=e[i^1].to;
}
maxflow+=incf[t];
mincost+=dis[t]*incf[t];
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m>>s>>t;
int u,v,w,c;
for(int i=1;i<=m;i++){
cin>>u>>v>>w>>c;
add(u,v,w,c);
add(v,u,0,-c);
}
while(spfa())update();
cout<<maxflow<<" "<<mincost;
return 0;
}
2.树
LCA
倍增
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
struct edge{
int next,to;
}e[N];
int head[N],cnt;
inline void add(int u,int v){
e[++cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int n,m,s;
int f[N][30],d[N];
void dfs(int u){
d[u]=d[f[u][0]]+1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==f[u][0]) continue;
f[v][0]=u;
dfs(v);
}
}
void init(){
for(int j=1;j<=22;j++){
for(int i=1;i<=n;i++){
f[i][j]=f[f[i][j-1]][j-1];
}
}
}
int lca(int u,int v){
if(d[u]<d[v]) swap(u,v);
for(int i=22;i>=0;i--){
if(d[f[u][i]]>=d[v]){
u=f[u][i];
}
}
if(u==v) return u;
for(int i=22;i>=0;i--){
if(f[u][i]!=f[v][i]){
u=f[u][i];
v=f[v][i];
}
}
return f[u][0];
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m>>s;
int u,v;
for(int i=1;i<n;i++){
cin>>u>>v;
add(u,v);
add(v,u);
}
dfs(s);
init();
while(m--){
cin>>u>>v;
cout<<lca(u,v)<<"\n";
}
return 0;
}
树剖
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
struct edge{
int next,to;
}e[N];
int head[N],cnt;
inline void add(int u,int v){
e[++cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int n,m,s,a[N];
int sz[N],d[N],fa[N],son[N],top[N];
void dfs1(int u){
sz[u]=1;
d[u]=d[fa[u]]+1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa[u]) continue;
fa[v]=u;
dfs1(v);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]){
son[u]=v;
}
}
}
void dfs2(int u,int tp){
top[u]=tp;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
if(son[u]) dfs2(son[u],tp);
}
int lca(int u,int v){
while(top[u]!=top[v]){
if(d[top[u]]<d[top[v]]) swap(u,v);
u=fa[top[u]];
}
if(d[u]>d[v]) swap(u,v);
return u;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m>>s;
int u,v;
for(int i=1;i<n;i++){
cin>>u>>v;
add(u,v);
add(v,u);
}
fa[s]=s;
dfs1(s);
dfs2(s,s);
while(m--){
cin>>u>>v;
cout<<lca(u,v)<<"\n";
}
return 0;
}
tarjan
杂项
KMP
#include<bits/stdc++.h>
#define debug puts("I will ak ioi")
#define next _yhr_tsq_
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
using namespace std;
constexpr int N=1e6+9;
int n,m;
string s,t;
int next[N];
void int_next(){
int j=0;
next[1]=0;
for(int i=2;i<=m;i++){
while(j&&t[j+1]!=t[i]) j=next[j];
if(t[j+1]==t[i]) ++j;
next[i]=j;
}
}
void kmp(){
int j=0;
for(int i=1;i<=n;i++){
while(j&&t[j+1]!=s[i]) j=next[j];
if(t[j+1]==s[i]) ++j;
if(j==m){
cout<<i-m+1<<"\n";
j=next[j];
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>s>>t;
n=s.size();m=t.size();
s=" "+s;t=" "+t;
int_next();
kmp();
return 0;
}
离散化
for(int i=1;i<=n;i++){
b[i]=a[i];
}
int m=n;
sort(b+1,b+1+n);
m=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+1+m,a[i])-b;
}