算法模板
数据结构
FHQ-Treap
int Q;
mt19937 seed(time(0));
uniform_int_distribution<int> rnd(0,2e9);
struct FHQTreap{
int lc,rc;
int key,num;
int siz;
}tr[N];
int tot,root;
int NewNode(int x){
tr[++tot]={0,0,x,rnd(seed),1};
return tot;
}
void Pushup(int p){
tr[p].siz=tr[tr[p].lc].siz+tr[tr[p].rc].siz+1;
}
void Buildtr(){
NewNode(-IINF); NewNode(IINF);
tr[1].rc=2; root=1;
if(tr[1].num<tr[2].num)
swap(tr[1].num,tr[2].num);
Pushup(1);
}
void Split(int p,int v,int &L,int &R){
if(!p) return L=R=0,void();
if(tr[p].key<=v)
L=p,Split(tr[p].rc,v,tr[p].rc,R);
else R=p,Split(tr[p].lc,v,L,tr[p].lc);
Pushup(p);
}
int Merge(int p,int q){
if(!p) return q;
if(!q) return p;
if(tr[p].num<tr[q].num){
tr[q].lc=Merge(p,tr[q].lc);
Pushup(q); return q;
}
else{
tr[p].rc=Merge(tr[p].rc,q);
Pushup(p); return p;
}
}
void Insert(int x){
int L,R,p=NewNode(x);
Split(root,x,L,R);
root=Merge(Merge(L,p),R);
}
void Delete(int x){
int L,R,P;
Split(root,x-1,L,R);
Split(R,x,P,R);
P=Merge(tr[P].lc,tr[P].rc);
root=Merge(Merge(L,P),R);
}
int AskVal(int p,int k){
if(!p) return -IINF;
if(tr[tr[p].lc].siz>=k) return AskVal(tr[p].lc,k);
else if(tr[tr[p].lc].siz+1==k) return tr[p].key;
else return AskVal(tr[p].rc,k-tr[tr[p].lc].siz-1);
}
int AskRank(int x){
int L,R,res;
Split(root,x-1,L,R);
res=tr[L].siz;
root=Merge(L,R);
return res;
}
int AskPre(int x){
int L,R;
Split(root,x-1,L,R);
int res=AskVal(L,tr[L].siz);
root=Merge(L,R);
return res;
}
int AskNxt(int x){
int L,R;
Split(root,x,L,R);
int res=AskVal(R,1);
root=Merge(L,R);
return res;
}
signed main(){
read(Q);
Buildtr();
while(Q--){
int op,x;
read(op),read(x);
if(op==1) Insert(x);
else if(op==2) Delete(x);
else if(op==3) printf("%d\n",AskRank(x));
else if(op==4) printf("%d\n",AskVal(root,x+1));
else if(op==5) printf("%d\n",AskPre(x));
else printf("%d\n",AskNxt(x));
}
return 0;
}
Splay
int Q,root,tot;
struct SplayTree{
int s[2],fa;
int key,cnt,siz;
#define lc s[0]
#define rc s[1]
}tr[N];
int NewNode(int v){
tr[++tot]={{0,0},0,v,1,1};
return tot;
}
void Pushup(int p){
tr[p].siz=tr[tr[p].lc].siz+tr[tr[p].rc].siz+tr[p].cnt;
}
int Dir(int p){return tr[tr[p].fa].s[1]==p;}
void Rotate(int x){
int y=tr[x].fa,z=tr[y].fa,c=Dir(x);
tr[y].s[c]=tr[x].s[c^1];
if(tr[x].s[c^1]) tr[tr[x].s[c^1]].fa=y;
tr[x].s[c^1]=y; tr[y].fa=x; tr[x].fa=z;
if(z) tr[z].s[y==tr[z].s[1]]=x;
Pushup(y); Pushup(x);
}
void Splay(int x){
while(tr[x].fa){
int y=tr[x].fa;
if(tr[y].fa){
if(Dir(y)==Dir(x)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
root=x;
}
void Insert(int v){
int p=root,q=0;
while(p){
q=p;
if(v<tr[p].key) p=tr[p].lc;
else if(tr[p].key==v) break;
else p=tr[p].rc;
}
// printf("Insert: P=%d,Q=%d\n",p,q);
if(p) tr[p].cnt++,tr[p].siz++;
else{
p=NewNode(v); tr[p].fa=q;
tr[q].s[v>tr[q].key]=p;
}
Splay(p);
}
void Delete(int v){
int p=root,q=0;
while(p){
q=p;
if(v==tr[p].key) break;
else if(v<tr[p].key) p=tr[p].lc;
else p=tr[p].rc;
}
Splay(p);
if(tr[p].cnt>1){
tr[p].cnt--;
tr[p].siz--;
return;
}
if(!tr[p].lc){
tr[tr[p].rc].fa=0;
root=tr[p].rc;
return;
}
q=tr[p].lc;
while(tr[q].rc) q=tr[q].rc;
tr[q].rc=tr[p].rc; tr[tr[p].rc].fa=q;
tr[tr[p].lc].fa=0; root=tr[p].lc;
Splay(q);
}
int AskPre(int v){
int p=root,q=0,res=-IINF;
while(p){
q=p;
if(tr[p].key<v) res=tr[p].key,p=tr[p].rc;
else p=tr[p].lc;
}
Splay(q); return res;
}
int AskNxt(int v){
int p=root,q=0,res=IINF;
while(p){
q=p;
if(tr[p].key>v) res=tr[p].key,p=tr[p].lc;
else p=tr[p].rc;
}
Splay(q); return res;
}
int AskRank(int v){
int p=root,q=0,res=0;
while(p){
q=p;
if(tr[p].key<v) res+=tr[tr[p].lc].siz+tr[p].cnt,p=tr[p].rc;
else p=tr[p].lc;
}
Splay(q); return res+1;
}
int AskVal(int k){
int p=root,q=0,res=0;
while(p){
q=p;
if(tr[tr[p].lc].siz>=k) p=tr[p].lc;
else if(tr[tr[p].lc].siz+tr[p].cnt>=k){res=tr[p].key;break;}
else k-=tr[tr[p].lc].siz+tr[p].cnt,p=tr[p].rc;
}
Splay(q); return res;
}
void Output(int x){
if(!x) return puts("Empty"),void();
printf("Tr[%d]: fa=%d,lc=%d,rc=%d,key=%d,siz=%d\n",x,tr[x].fa,tr[x].lc,tr[x].rc,tr[x].key,tr[x].siz);
}
void Print(int p,string s,bool fir){
cout<<s<<(fir?"+---":"\\---");
Output(p);
if(!p) return;
s+=fir?"| ":" ";
Print(tr[p].lc,s,1);
Print(tr[p].rc,s,0);
}
signed main(){
read(Q);
while(Q--){
int op,x;
read(op),read(x);
if(op==1) Insert(x);
else if(op==2) Delete(x);
else if(op==3) printf("%d\n",AskRank(x));
else if(op==4) printf("%d\n",AskVal(x));
else if(op==5) printf("%d\n",AskPre(x));
else printf("%d\n",AskNxt(x));
// Print(root,"",1);
}
return 0;
}
字符串
KMP
char a[N],b[N];
int nxt[N],j,n,m;
vector<int> pos;
signed main() {
scanf("%s",a+1);
scanf("%s",b+1);
n=strlen(a+1);
m=strlen(b+1);
for(int i=2;i<=m;i++){
while(j>0&&b[i]!=b[j+1]) j=nxt[j];
if(b[i]==b[j+1]) j++;
nxt[i]=j;
}
j=0;
for(int i=1;i<=n;i++){
while(j>0&&(j==n||a[i]!=b[j+1])) j=nxt[j];
if(a[i]==b[j+1]) j++;
if(j==m) pos.push_back(i-j+1);
}
for(int i=0;i<pos.size();i++){
cout<<pos[i]<<endl;
}
for(int i=1;i<=m;i++){
cout<<nxt[i]<<" ";
}
cout<<endl;
return 0;
}
ExKMP / Algorithm Z
int n,m;
char a[N],b[N];
int z[N],ext[N];
void ExKMP(){
for(int i=2,k=1;i<=m;i++){
if(k+z[k]-1>=i) z[i]=min(z[i-k+1],k+z[k]-i);
while(i+z[i]<=m&&b[i+z[i]]==b[z[i]+1]) z[i]++;
if(i+z[i]>k+z[k]) k=i;
}
for(int i=1,k=0;i<=n;i++){
if(k+ext[k]-1>=i) ext[i]=min(z[i-k+1],k+ext[k]-i);
while(ext[i]<m&&i+ext[i]<=n&&a[i+ext[i]]==b[ext[i]+1]) ext[i]++;
if(i+ext[i]>k+ext[k]) k=i;
}
z[1]=m;
}
ACAM
int n;
string s[N],t;
int ed[N],tot=1;
struct Trie{
int son[29];
int fail,cnt,in;
}tr[N];
void Insert(string x,int id){
int len=x.length(),p=1;
for(int i=0;i<len;i++){
int c=x[i]-'a';
if(!tr[p].son[c])
tr[p].son[c]=++tot;
p=tr[p].son[c];
}
ed[id]=p;
}
void BuildAC(){
queue<int> q;
for(int i=0;i<26;i++)
tr[0].son[i]=1;
tr[1].fail=0;
q.push(1);
while(q.size()){
int p=q.front();
// printf("Tr[%d].Fail=%d\n",p,tr[p].fail);
q.pop();
for(int i=0;i<26;i++){
if(!tr[p].son[i])
tr[p].son[i]=tr[tr[p].fail].son[i];
else{
tr[tr[p].son[i]].fail=tr[tr[p].fail].son[i];
q.push(tr[p].son[i]);
}
}
}
for(int i=1;i<=tot;i++){
tr[tr[i].fail].in++;
// printf("Tr[%d].fail=%d\n",i,tr[i].fail);
}
}
void Query(){
int p=1,len=t.length();
for(int i=0;i<len;i++){
int c=t[i]-'a';
p=tr[p].son[c];
tr[p].cnt++;
}
}
void TopoSort(){
queue<int> q;
for(int i=1;i<=tot;i++){
if(!tr[i].in)
q.push(i);
}
while(q.size()){
int x=q.front();
q.pop();
int y=tr[x].fail;
tr[y].cnt+=tr[x].cnt;
if(!(--tr[y].in))
q.push(y);
}
}
signed main(){
read(n);
for(int i=1;i<=n;i++){
cin>>s[i];
Insert(s[i],i);
}
cin>>t;
BuildAC();
Query();
TopoSort();
for(int i=1;i<=n;i++) printf("%d\n",tr[ed[i]].cnt);
return 0;
}
SA
int n,m;
char a[N];
int rk[N],tp[N],sa[N],c[N];
#define V(x) min((x),n+1)
signed main(){
scanf("%s",a+1);
n=strlen(a+1);
m='z';
for(int i=1;i<=n;i++)
rk[i]=a[i],c[rk[i]]++;
for(int i=1;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i;i--) sa[c[rk[i]]--]=i;
for(int k=1;k<=n;k<<=1){
int p=0;
for(int i=n-k+1;i<=n;i++) tp[++p]=i;
for(int i=1;i<=n;i++)
if(sa[i]>k) tp[++p]=sa[i]-k;
for(int i=1;i<=m;i++) c[i]=0;
for(int i=1;i<=n;i++) c[rk[i]]++;
for(int i=1;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i;i--) sa[c[rk[tp[i]]]--]=tp[i];
memcpy(tp,rk,sizeof(tp));
rk[sa[1]]=m=1;
for(int i=2;i<=n;i++){
if(tp[sa[i]]==tp[sa[i-1]]&&tp[V(sa[i]+k)]==tp[V(sa[i-1]+k)]) rk[sa[i]]=m;
else rk[sa[i]]=++m;
}
if(m==n) break;
}
for(int i=1;i<=n;i++) printf("%d ",sa[i]);
return 0;
}
图论
匈牙利
int n,m,k;
int head[N],tot;
int mch[N];
bool vis[N];
struct Edge{
int to,nxt;
}edge[M];
void Add(int u,int v){
edge[++tot]={v,head[u]};
head[u]=tot;
}
bool dfs(int x){
for(int i=head[x];i;i=edge[i].nxt){
int t=edge[i].to;
if(vis[t]) continue;
vis[t]=1;
if(!mch[t]||dfs(mch[t])){
mch[t]=x;
return 1;
}
}
return 0;
}
signed main(){
read(n),read(m),read(k);
for(int i=1;i<=k;i++){
int u,v;
read(u),read(v);
Add(u,v);
}
int ans=0;
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
ans+=dfs(i);
}
printf("%d\n",ans);
return 0;
}
KM
int n,m;
struct Edge{
int to,val;
};
vector<Edge> e[N];
ll ha[N],hb[N],upd[N];
bool va[N],vb[N];
int pre[N],mch[N];
void Clear(){
memset(va,0,sizeof(va));
memset(vb,0,sizeof(vb));
memset(upd,0x3f,sizeof(upd));
memset(pre,0,sizeof(pre));
}
bool dfs(int x,int pr){
va[x]=1;
for(Edge i:e[x]){
int t=i.to,w=i.val;
if(vb[t]) continue;
if(ha[x]+hb[t]==w){
vb[t]=1; pre[t]=pr;
if(!mch[t]||dfs(mch[t],t)){
mch[t]=x;
return 1;
}
}
else if(ha[x]+hb[t]-w<upd[t]){
upd[t]=ha[x]+hb[t]-w;
pre[t]=pr;
}
}
return 0;
}
void KMSolve(){
for(int i=1;i<=n;i++){
Clear();
int st=0; mch[0]=i;
while(mch[st]){
if(dfs(mch[st],st)) break;
ll delta=LINF;
for(int j=1;j<=n;j++){
if(!vb[j]&&upd[j]<delta)
delta=upd[j],st=j;
}
for(int j=1;j<=n;j++){
if(va[j]) ha[j]-=delta;
if(vb[j]) hb[j]+=delta;
else upd[j]-=delta;
}
vb[st]=1;
}
while(st){
mch[st]=mch[pre[st]];
st=pre[st];
}
}
ll ans=0;
for(int i=1;i<=n;i++) ans+=ha[i]+hb[i];
printf("%lld\n",ans);
for(int i=1;i<=n;i++) printf("%d ",mch[i]);
puts("");
}
signed main(){
read(n),read(m);
memset(ha,-0x3f,sizeof(ha));
for(int i=1;i<=m;i++){
int u,v,w;
read(u),read(v),read(w);
e[u].push_back(Edge{v,w});
Ckmax(ha[u],1ll*w);
}
KMSolve();
return 0;
}
最大流-Dinic
int n,m,S,T;
int head[N],tot=1,hd[N];
ll ans;
int dis[N];
struct Edge{
int to,nxt;
ll val;
}edge[M];
void Add(int u,int v,ll w){
edge[++tot]={v,head[u],w};
head[u]=tot;
}
bool Bfs(){
memset(dis,0,sizeof(dis));
queue<int> q;
q.push(S); hd[S]=head[S]; dis[S]=1;
while(q.size()){
int x=q.front(); q.pop();
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(!dis[y]&&edge[i].val){
dis[y]=dis[x]+1;
hd[y]=head[y];
if(y==T) return 1;
q.push(y);
}
}
}
return 0;
}
ll Dinic(int x,ll flow){
if(x==T) return flow;
ll res=0;
for(int &i=hd[x];i;i=edge[i].nxt){
int y=edge[i].to;
ll w=edge[i].val;
if(w&&dis[x]+1==dis[y]){
ll v=Dinic(y,min(flow-res,w));
if(!v) dis[y]=0;
edge[i].val-=v,edge[i^1].val+=v;
res+=v;
}
if(res==flow) break;
}
return res;
}
signed main(){
read(n),read(m),read(S),read(T);
for(int i=1;i<=m;i++){
int u,v; ll w;
read(u),read(v),read(w);
Add(u,v,w);
Add(v,u,0);
}
while(Bfs()) ans+=Dinic(S,LINF);
printf("%lld\n",ans);
return 0;
}
HLPP
int n,m,S,T;
int head[N],tot=1,h[N],gap[N<<1],ex[N];
bool vis[N];
struct Edge{
int to,nxt,val;
}edge[M];
void Add(int u,int v,int w){
edge[++tot]={v,head[u],w};
head[u]=tot;
}
void Bfs(){
queue<int> qu;
memset(h,0x3f,sizeof(h));
h[T]=0;
qu.push(T);
while(qu.size()){
int x=qu.front(); qu.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(vis[y]) continue;
if(edge[i^1].val&&h[y]>h[x]+1){
h[y]=h[x]+1;
qu.push(y);
}
}
}
}
struct Node{
int x;
bool operator<(const Node& tmp)const{
return h[x]<h[tmp.x];
}
};
priority_queue<Node> q;
void PushFlow(int x){
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
int w=min(edge[i].val,ex[x]);
if(w&&h[y]==h[x]-1){
ex[y]+=w,ex[x]-=w;
edge[i].val-=w,edge[i^1].val+=w;
if(!vis[y]&&y!=S&&y!=T) q.push(Node{y}),vis[y]=1;
}
if(!ex[x]) return;
}
}
void Relabel(int x){
int mn=IINF;
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(edge[i].val) Ckmin(mn,h[y]);
}
h[x]=mn+1;
}
int HLPP(){
Bfs();
if(h[S]>1e9) return 0;
h[S]=n;
for(int i=1;i<=n;i++){
if(h[i]<1e9) gap[h[i]]++;
vis[i]=0;
}
for(int i=head[S];i;i=edge[i].nxt){
int y=edge[i].to,w=edge[i].val;
if(edge[i].val){
ex[y]+=w,ex[S]-=w;
edge[i].val-=w,edge[i^1].val+=w;
if(y!=T&&y!=S&&!vis[y]&&h[y]<1e9) q.push(Node{y}),vis[y]=1;
}
}
while(q.size()){
int x=q.top().x; q.pop(); vis[x]=0;
PushFlow(x);
if(!ex[x]) continue;
if(!(--gap[h[x]])){
for(int i=1;i<=n;i++){
if(i!=S&&i!=T&&h[i]>h[x]&&h[i]<n+1)
--gap[h[i]],h[i]=n+1,++gap[n+1];
}
}
Relabel(x);
gap[h[x]]++;
vis[x]=1; q.push(Node{x});
}
return ex[T];
}
signed main(){
read(n),read(m),read(S),read(T);
for(int i=1;i<=m;i++){
int u,v,w;
read(u),read(v),read(w);
Add(u,v,w),Add(v,u,0);
}
int ans=HLPP();
printf("%d\n",ans);
return 0;
}
数论
Exgcd
ll T,A,B,C,x,y,d,x1,x2,y1,y2,cnt;
ll GetX(ll Y){return (C-B*Y)/A;}
ll GetY(ll X){return (C-A*X)/B;}
ll Exgcd(ll a,ll b,ll &x,ll &y){
if(b==0) return x=1,y=0,a;
ll res=Exgcd(b,a%b,x,y);
ll z=x;
x=y;
y=z-(a/b)*y;
return res;
}
void Solve(){
read(A),read(B),read(C);
d=Exgcd(A,B,x,y);
if(C%d) return puts("-1"),void();
A/=d,B/=d,C/=d;
x*=C,y*=C;
x1=((x-1)%B+B)%B+1;
y2=GetY(x1);
y1=((y-1)%A+A)%A+1;
x2=GetX(y1);
cnt=(x2-x1)/B+1;
if(y2<=0) printf("%lld %lld\n",x1,y1);
else printf("%lld %lld %lld %lld %lld\n",cnt,x1,y1,x2,y2);
}
CRT
ll n,m[N],a[N],ans,M=1,x,y;
ll Exgcd(ll a,ll b,ll &x,ll &y){
if(!b) return x=1,y=0,a;
ll res=Exgcd(b,a%b,x,y);
ll z=x;
x=y,y=z-a/b*y;
return res;
}
void Solve(){
for(int i=1;i<=n;i++) M*=m[i];
for(int i=1;i<=n;i++){
ll Mi=M/m[i];
ll d=Exgcd(Mi,m[i],x,y);
x=((x-1)%(m[i]/d)+m[i]/d)%(m[i]/d)+1;
ans=(ans+SlowMul(SlowMul(x,Mi),a[i]))%M;
}
printf("%lld\n",ans);
}
ExCRT
ll Solve(){
M=b[1],R=a[1];
for(int i=2;i<=n;i++){
ll A=M,B=b[i],C=a[i]-R;
C=(C%B+B)%B;
ll d=Exgcd(A,B,x,y);
if(C%d) return -1;
M=M/Exgcd(M,b[i],tmp1,tmp2)*b[i];
x=WangbaMul(x,C/d,B/d);
x=(x%(B/d)+(B/d))%(B/d);
R+=x*A; R%=M;
}
return R%M;
}
FWT
int n;
ll a[N],b[N],c[N];
ll ta[N],tb[N];
const ll mod=998244353,inv2=(mod+1)>>1;
inline ll Mod(ll x){return (x>=mod)?(x-mod):(x);}
inline void Add(ll &x,ll y){x=Mod(x+y);}
void FWTAnd(ll f[],int type){
for(int len=2;len<=n;len<<=1){
int k=len>>1;
for(int i=0;i<n;i+=len){
for(int j=0;j<k;j++){
Add(f[i+j],Mod(f[i+j+k]*type+mod));
}
}
}
}
void FWTOr(ll f[],int type){
for(int len=2;len<=n;len<<=1){
int k=len>>1;
for(int i=0;i<n;i+=len){
for(int j=0;j<k;j++)
Add(f[i+j+k],Mod(f[i+j]*type+mod));
}
}
}
void FWTXor(ll f[],int type){
for(int len=2;len<=n;len<<=1){
int k=len>>1;
for(int i=0;i<n;i+=len){
for(int j=0;j<k;j++){
Add(f[i+j],f[i+j+k]);
f[i+j+k]=Mod(f[i+j]-Mod(f[i+j+k]<<1)+mod);
if(type==-1) (f[i+j]*=inv2)%=mod,(f[i+j+k]*=inv2)%=mod;
}
}
}
}
void MulAnd(){
FWTAnd(a,1),FWTAnd(b,1);
for(int i=0;i<n;i++) c[i]=a[i]*b[i]%mod;
FWTAnd(c,-1);
}
void MulOr(){
FWTOr(a,1),FWTOr(b,1);
for(int i=0;i<n;i++) c[i]=a[i]*b[i]%mod;
FWTOr(c,-1);
}
void MulXor(){
FWTXor(a,1),FWTXor(b,1);
for(int i=0;i<n;i++) c[i]=a[i]*b[i]%mod;
FWTXor(c,-1);
}
signed main(){
read(n); n=1<<n;
for(int i=0;i<n;i++) read(a[i]);
for(int i=0;i<n;i++) read(b[i]);
memcpy(ta,a,sizeof(a)); memcpy(tb,b,sizeof(b));
MulOr(); for(int i=0;i<n;i++) printf("%lld ",c[i]); puts("");
memcpy(a,ta,sizeof(a)); memcpy(b,tb,sizeof(b));
MulAnd(); for(int i=0;i<n;i++) printf("%lld ",c[i]); puts("");
memcpy(a,ta,sizeof(a)); memcpy(b,tb,sizeof(b));
MulXor(); for(int i=0;i<n;i++) printf("%lld ",c[i]); puts("");
memcpy(a,ta,sizeof(a)); memcpy(b,tb,sizeof(b));
return 0;
}