模板整理
未附加题目链接的板子均为核心代码。
最大流
void addedge(int u, int v, int w) //tot=1
{
nxt[++tot]=head[u],head[u]=tot,to[tot]=v,wei[tot]=w;
nxt[++tot]=head[v],head[v]=tot,to[tot]=u,wei[tot]=0;
}
bool bfs()
{
memset(lev,-1,sizeof(lev));
int l=0,r=0;
q[0]=s; lev[s]=1;
while(l<=r)
{
int u=q[l++];
for(int e=head[u];e;e=nxt[e])
if(lev[to[e]]==-1&&wei[e])
{
lev[to[e]]=lev[u]+1;
if(to[e]==t) return true;
q[++r]=to[e];
}
}
return false;
}
int dfs(int u, int mx)
{
if(u==t) return mx;
int l=mx;
for(int e=head[u];e&&l;e=nxt[e])
if(lev[to[e]]==lev[u]+1&&wei[e]>0)
{
int f=dfs(to[e],min(l,wei[e]));
if(!f) lev[to[e]]=-1;
l-=f,wei[e]-=f,wei[e^1]+=f;
}
return mx-l;
}
最小费用流
void addedge(int u, int v, int w, int c)
{
nxt[++tot]=head[u],head[u]=tot,to[tot]=v,wei[tot]=w,cost[tot]=c;
nxt[++tot]=head[v],head[v]=tot,to[tot]=u,wei[tot]=0,cost[tot]=-c;
}
bool spfa()
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=t;++i) dis[i]=inf;
queue<int> q;
q.push(t),dis[t]=0;
while(!q.empty())
{
int u=q.front();
q.pop(), vis[u]=false;
for(int e=head[u];e;e=nxt[e])
if(wei[e^1]&&dis[to[e]]>dis[u]-cost[e])
{
dis[to[e]]=dis[u]-cost[e];
if(!vis[to[e]]) vis[to[e]]=true,q.push(to[e]);
}
}
return dis[s]!=inf;
}
int dfs(int u, int mx)
{
vis[u]=true;
if(u==t) return mx;
int l=mx;
for(int e=head[u];e&&l;e=nxt[e])
if(!vis[to[e]]&&wei[e]>0&&dis[to[e]]==dis[u]-cost[e])
{
int f=dfs(to[e],min(l,wei[e]));
ans+=f*cost[e];
l-=f,wei[e]-=f,wei[e^1]+=f;
}
return mx-l;
}
LOJ104 普通平衡树
#include<cstdio>
namespace io {
const int SIZE=(1<<21)+1;
char ibuf[SIZE],*iS,*iT,c; int qr;
#define gc()(iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
inline int gi (){
int x=0,f=1;
for(c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
for(;c<='9'&&c>='0';c=gc()) x=(x<<1)+(x<<3)+(c&15); return x*f;
}
} using io::gi;
const int N=200005,inf=1<<30;
int fa[N],ch[N][2],size[N],val[N],mp[N],cnt[N],t,rt;
void pushup(int x) {
size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
}
void rotate(int x)
{
int y=fa[x],z=fa[y];
int k=ch[y][1]==x,w=ch[x][!k];
ch[z][ch[z][1]==y]=x;
ch[x][!k]=y,ch[y][k]=w;
fa[w]=y,fa[y]=x,fa[x]=z;
pushup(y),pushup(x);
}
void splay(int x, int k)
{
while(fa[x]!=k)
{
int y=fa[x],z=fa[y];
if(z!=k) (ch[z][1]==y)^(ch[y][1]==x)?rotate(x):rotate(y);
rotate(x);
}
pushup(x);
if(!k) rt=x;
}
void insert(int x)
{
int u=rt,f=0;
while(u&&val[u]!=x) f=u,u=ch[u][x>val[u]];
if(u) ++cnt[u];
else
{
u=++t,val[u]=x,cnt[u]=size[u]=1,mp[t]=u;
if(f) ch[f][x>val[f]]=u,fa[u]=f;
}
splay(u,0);
}
int findk(int x)
{
int u=rt;
while(true)
{
if(x>size[ch[u][0]]+cnt[u]) x-=size[ch[u][0]]+cnt[u],u=ch[u][1];
else if(x<=size[ch[u][0]]) u=ch[u][0];
else return val[u];
}
}
void makert(int x)
{
int u=rt;
while(ch[u][x>val[u]]&&val[u]!=x) u=ch[u][x>val[u]];
splay(u,0);
}
int getrk(int x)
{
int u=rt,rnk=0;
while(u)
{
if(x<val[u]) u=ch[u][0];
else
{
rnk+=size[ch[u][0]];
if(val[u]==x)
{
splay(u,0);
return rnk+1;
}
rnk+=cnt[u];
u=ch[u][1];
}
}
return rnk;
}
int findpre(int x)
{
makert(x);
if(val[rt]<x) return rt;
int u=ch[rt][0];
while(ch[u][1])u=ch[u][1];
return u;
}
int findnxt(int x)
{
makert(x);
if(val[rt]>x) return rt;
int u=ch[rt][1];
while(ch[u][0])u=ch[u][0];
return u;
}
void remove(int u)
{
int x=findpre(u),y=findnxt(u);
splay(x,0);
if(y) splay(y,x);
if(cnt[ch[y][0]]>1) --cnt[ch[y][0]],splay(ch[y][0],0);
else ch[y][0]=0;
}
int main()
{
int n=gi();
insert(-inf),insert(inf);
while(n--)
{
int op=gi(),x=gi();
if(op==1) insert(x);
if(op==2) remove(x);
if(op==3) printf("%d\n",getrk(x)-1);
if(op==4) printf("%d\n",findk(x+1));
if(op==5) printf("%d\n",val[findpre(x)]);
if(op==6) printf("%d\n",val[findnxt(x)]);
}
}
LOJ105 文艺平衡树
#include<cstdio>
#include<algorithm>
inline int gi()
{
char c; int x=0;
for(;c<'0'||c>'9';c=getchar());
for(;c>='0'&&c<='9';c=getchar())x=(x<<1)+(x<<3)+c-'0';
return x;
}
const int N=100005;
int ch[N][2],fa[N],size[N],rev[N],a[N],val[N],rt,id,n,m;
void pushup(int x) {
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void pushdown(int x)
{
if(!rev[x]) return ;
if(ch[x][0]) rev[ch[x][0]]^=1;
if(ch[x][1]) rev[ch[x][1]]^=1;
std::swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
void rotate(int x)
{
int y=fa[x],z=fa[y];
int k=ch[y][1]==x,w=ch[x][!k];
ch[z][ch[z][1]==y]=x,ch[x][!k]=y,ch[y][k]=w;
fa[w]=y,fa[y]=x,fa[x]=z;
pushup(y),pushup(x);
}
void splay(int x, int k)
{
while(fa[x]!=k)
{
int y=fa[x],z=fa[y];
pushdown(z),pushdown(y),pushdown(x);
if(z!=k) (ch[z][1]==y)^(ch[y][1]==x)?rotate(x):rotate(y);
rotate(x);
}
if(!k) rt=x;
}
void build(int& x, int l, int r, int f)
{
if(l>r) return ;
x=++id; int mid=l+r>>1;
val[x]=a[mid],size[x]=1,fa[x]=f;
build(ch[x][0],l,mid-1,x);
build(ch[x][1],mid+1,r,x);
pushup(x);
}
int findk(int k)
{
int u=rt;
while(true)
{
pushdown(u);
if(size[ch[u][0]]+1==k) return u;
if(k>size[ch[u][0]]+1) k-=size[ch[u][0]]+1,u=ch[u][1];
else u=ch[u][0];
}
}
int split(int x, int y)
{
int l=findk(x),r=findk(y+2);
splay(l,0),splay(r,l);
return r;
}
void solve(int u)
{
pushdown(u);
if(ch[u][0]) solve(ch[u][0]);
if(1<=val[u]&&val[u]<=n) printf("%d ",val[u]);
if(ch[u][1]) solve(ch[u][1]);
}
int main()
{
n=gi(),m=gi();
for(int i=2;i<=n+2;++i) a[i]=i-1;
build(rt,1,n+2,0);
while(m--)
{
int l=gi(),r=gi();
int x=split(l,r);
rev[ch[x][0]]^=1;
}
solve(rt);
}
分治 NTT
void init(int x)
{
for(m=1;m<=x;m<<=1,++l);
for(int i=0;i<m;++i) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
}
#define mul(x,y) (1ll*x*y%Mod)
namespace poly
{
int r[N],a[N],b[N],w[N],iw[N],m,l;
void init(int x)
{
for(m=1,l=0;m<=x;m<<=1,++l);
for(int i=0;i<m;++i) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
int b=po(3,(Mod-1)/m),ib=po(b,Mod-2);
w[m/2]=iw[m/2]=1;
for(int i=1;i<m/2;++i) w[m/2+i]=mul(w[m/2+i-1],b),iw[m/2+i]=mul(iw[m/2+i-1],ib);
for(int i=m/2-1;i;--i) w[i]=w[i<<1],iw[i]=iw[i<<1];
}
void ntt(int* a, int f)
{
for(int i=0;i<m;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1,id=1;i<m;i<<=1,++id)
{
for(int j=0;j<m;j+=i<<1)
for(int k=0;k<i;++k)
{
int x=a[j+k],y=mul((f==1?w[i+k]:iw[i+k]),a[i+j+k]);
a[j+k]=(x+y>=Mod?x+y-Mod:x+y);
a[i+j+k]=(x-y<0?x-y+Mod:x-y);
}
}
if(f==-1)
{
int in=po(m,Mod-2);
for(int i=0;i<m;++i) a[i]=mul(a[i],in);
}
}
void cdqntt(int l, int r)
{
if(l==r)
{
if(!l) f[l]=1;
return ;
}
int mid=l+r>>1;
cdqntt(l,mid);
for(int i=l;i<=mid;++i) a[i-l]=f[i];
for(int i=1;i<=r-l+1;++i) b[i]=g[i];
if(r-l+1<=85)
{
for(int i=0;i<=mid-l;++i)
for(int j=max(1,mid-i-l+1);j<=r-l+1&&i+j+l<=r;++j) upd(f[i+j+l],mul(a[i],b[j]));
}
else
{
init(r-l);
memset(a+(mid-l+1),0,sizeof(int)*(m-(mid-l+1)));
memset(b+(r-l+2),0,sizeof(m-(r-l+2)));
ntt(a,1),ntt(b,1);
for(int i=0;i<m;++i) a[i]=mul(a[i],b[i]);
ntt(a,-1);
for(int i=mid+1;i<=r;++i) upd(f[i],a[i-l]);
}
cdqntt(mid+1,r);
}
}
后缀排序
void Sort()
{
memset(tm,0,sizeof(int)*(m+1));
for(int i=1;i<=n;++i) ++tm[rk[i]];
for(int i=1;i<=m;++i) tm[i]+=tm[i-1];
for(int i=n;i>=1;--i) sa[tm[rk[se[i]]]--]=se[i];
}
void getsa()
{
for(int i=1;i<=n;++i) rk[i]=s[i],se[i]=i;
Sort();
for(int h=1;h<=n;h<<=1)
{
int cnt=0;
for(int i=n-h+1;i<=n;++i) se[++cnt]=i;
for(int i=1;i<=n;++i) if(sa[i]>h) se[++cnt]=sa[i]-h;
Sort();
std::swap(rk,se);
rk[sa[1]]=cnt=1;
for(int i=2;i<=n;++i)
rk[sa[i]]=(se[sa[i]]==se[sa[i-1]]&&se[sa[i]+h]==se[sa[i-1]+h])?cnt:++cnt;
m=cnt;
if(m>=n) break;
}
int k=0;
for(int i=1;i<=n;++i)
{
if(k) --k;
int j=sa[rk[i]-1];
while(s[i+k]==s[j+k]) ++k;
hei[rk[i]]=k;
}
}
k 大异或和
void ins(ll a)
{
for(int i=50;i>=0;i--)
if((a>>i)&1ll)
{
if(v[i]) a^=v[i];
else {v[i]=a;return;}
}
if(!a) flag=1;
return;
}
void check()
{
for(int i=50;i>=0;i--)
for(int j=i-1;j>=0;j--)
if((v[i]>>j)&1) v[i]^=v[j];
for(int i=50;i>=0;i--) cnt+=(v[i]>0);
}
ll query(ll k)
{
if(k>(1ll<<cnt)) return -1;
if(flag) k--;
if(k==-1) return 0;
ll res=0;
for(int i=0;i<=50&&k;i++)
if(v[i])
{
res^=(k&1)*v[i];
k>>=1;
}
return res;
}
LCT
#define isnrt(x) (ch[fa[x]][0]==x||ch[fa[x]][1]==x)
void pushup(int x) { /*...*/ }
void pushdown(int x)
{
if(rev[x])
{
rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
}
void rotate(int x)
{
int y=fa[x],z=fa[y];
int k=ch[y][1]==x,w=ch[x][!k];
if(isnrt(y)) ch[z][ch[z][1]==y]=x;
ch[x][!k]=y,ch[y][k]=w;
fa[w]=y,fa[y]=x,fa[x]=z;
pushup(y),pushup(x);
}
void splay(int x)
{
int y=x,tp=1; st[1]=y;
while(isnrt(y)) st[++tp]=y=fa[y];
while(tp) pushdown(st[tp--]);
while(isnrt(x))
{
int y=fa[x],z=fa[y];
if(isnrt(y)) (ch[z][1]==y)^(ch[y][1]==x)?rotate(x):rotate(y);
rotate(x);
}
pushup(x);
}
void access(int x) { int y=0; for(;x;y=x,x=fa[x]) splay(x),ch[x][1]=y,pushup(x); }
void makert(int x) { access(x),splay(x),rev[x]^=1; }
void link(int x, int y) { makert(x); fa[x]=y; }
void split(int x, int y) { makert(x),access(y),splay(y); }
void cut(int x, int y) { split(x,y); ch[y][0]=fa[x]=0; }
后缀自动机
void extend(int c)
{
int p=lst,np=++cnt;lst=np;
len[np]=len[p]+1,size[np]=1;
for(;p&&!ch[p][c];p=pre[p]) ch[p][c]=np;
if(!p) {
pre[np]=1;
return ;
}
int q=ch[p][c];
if(len[p]+1==len[q]) {
pre[np]=q;
return ;
}
int nq=++cnt;len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
pre[nq]=pre[q],pre[q]=pre[np]=nq;
for(;ch[p][c]==q;p=pre[p])ch[p][c]=nq;
}
高斯消元
void gauss(int n)
{
for(int i=1;i<=n;++i)
{
int r=i;
for(int j=i+1;j<=n;++j) if(fabs(a[r][i])<fabs(a[j][i])) r=j;
if(r!=i) swap(a[i],a[r]);
for(int j=n+1;j>=i;--j) a[i][j]/=a[i][i];
for(int j=i+1;j<=n;++j)
for(int k=n+1;k>=i;--k) a[j][k]-=a[j][i]*a[i][k];
}
ans[n]=a[n][n+1];
for(int i=n-1;i;--i)
{
ans[i]=a[i][n+1];
for(int j=i+1;j<=n;++j) ans[i]-=a[i][j]*ans[j];
}
}
自然数幂和(拉格朗日插值)
int lagpow(ll n, int c)
{
c+=2;
inv[0]=inv[1]=1;
for(int i=2;i<=c;++i) inv[i]=mul(Mod-Mod/i,inv[Mod%i]);
for(int i=2;i<=c;++i) inv[i]=mul(inv[i],inv[i-1]);
pre[0]=suf[c+1]=1;
for(int i=1;i<=c;++i) pre[i]=mul(pre[i-1],(n-i)%Mod);
for(int i=c;i>=1;--i) suf[i]=mul(suf[i+1],(n-i)%Mod);
int sum=0,ans=0;
for(int i=1;i<=c;++i)
{
sum=add(sum,po(i,c-2));
int t=mul(mul(inv[i-1],inv[c-i]),mul(pre[i-1],suf[i+1]));
t=mul(t,sum);
ans=((c-i&1)?sub(ans,t):add(ans,t));
}
return ans;
}