(纯手打,持续更新中…)
文章目录
数学
exGCD
inline void exgcd(ll a,ll b,ll &x,ll &y){
if (!b) {x=1,y=0;return;}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
FFT
非递归版
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define pi acos(-1.0)
#define N 4000050
using namespace std;
int n,m,r[N],l=0;
struct com
{
double x,y;
inline com operator +(com b) {com ret;ret.x=x+b.x,ret.y=y+b.y;return ret;}
inline com operator -(com b) {com ret;ret.x=x-b.x,ret.y=y-b.y;return ret;}
inline com operator *(com b) {com ret;ret.x=x*b.x-y*b.y,ret.y=y*b.x+x*b.y;return ret;}
}s[N*2],t[N*2];
inline void fft(com a[],int k)
{
for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
for (int i=1;i<n;i<<=1)
{
com w,wn,X,Y;
wn.x=cos(pi/i),wn.y=k*sin(pi/i);
for (int j=0;j<n;j+=(i<<1))
{
w.x=1,w.y=0;
for (int _=0;_<i;_++,w=w*wn)
{
X=a[j+_],Y=w*a[j+_+i];
a[j+_]=X+Y,a[j+_+i]=X-Y;
}
}
}
if (k==-1) for (int i=0;i<n;i++) a[i].x/=n;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=0;i<=n;i++) scanf("%lf",&s[i].x);
for (int i=0;i<=m;i++) scanf("%lf",&t[i].x);
for (m+=n,n=1;n<=m;n*=2) l++;
for (int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
fft(s,1),fft(t,1);
for (int i=0;i<=n;i++) s[i]=s[i]*t[i];
fft(s,-1);
for (int i=0;i<=m;i++) printf("%.0lf ",s[i].x+0.4);
}
线性求逆元
需要推一下公式
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 3000050
using namespace std;
typedef long long ll;
int inv[N],i,n,p;
int main()
{
scanf("%d%d",&n,&p),inv[0]=0,inv[1]=1;
printf("1\n");
for (int i=2;i<=n;i++) inv[i]=(ll)(p-p/i)*inv[p%i]%p,printf("%d\n",inv[i]);
return 0;
}
NTT
g表示p的原根
本质上和FFT一样
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define p 1005060097
#define g 5
#define N 500050
using namespace std;
typedef long long ll;
ll a[N],b[N];
int n,m,r[N],l;
template<class _T>inline void read(_T &x)
{
x=0;
char ch=getchar();
int f=0;
while (!isdigit(ch)) {if (ch=='-') f=1;ch=getchar();}
while (isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
if (f) x=-x;
}
inline ll qsm(ll x,ll y)
{
ll ret=1;
while (y)
{
if (y&1) ret=ret*x%p;
x=x*x%p,y/=2;
}
return ret;
}
inline void ntt(ll a[],int k)
{
for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
for (int i=1;i<n;i<<=1)
{
ll w,wn,X,Y;
if (k==1) wn=qsm(g,(p-1)/(i<<1));else wn=qsm(g,p-1-(p-1)/(i<<1));
for (int j=0;j<n;j+=(i<<1))
{
w=1ll;
for (int _=0;_<i;_++,w=w*wn%p)
{
X=a[j+_],Y=w*a[j+_+i]%p;
a[j+_]=(X+Y)%p,a[j+_+i]=(X-Y+p)%p;
}
}
}
if (k==-1)
{
ll inv=qsm(n,p-2);
for (int i=0;i<n;i++) a[i]=a[i]*inv%p;
}
}
int main()
{
read(n),read(m);
for (int i=0;i<=n;i++) read(a[i]);
for (int i=0;i<=m;i++) read(b[i]);
for (m+=n,n=1,l=0;n<=m;n<<=1) l++;
for (int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
ntt(a,1),ntt(b,1);
for (int i=0;i<=n;i++) a[i]=a[i]*b[i]%p;
ntt(a,-1);
for (int i=0;i<=m;i++) printf("%lld ",a[i]);
}
FWT
#include<bits/stdc++.h>
#define p 998244353
#define inv 499122177
#define N 600050
using namespace std;
typedef long long ll;
ll n,a[N],b[N],c[N],nn;
inline void fwt(ll a[],int t,int k){
ll X,Y;
if (t==1){// or
for (int i=1;i<n;i<<=1){
for (int j=0;j<n;j++) if (i&j) a[j]=(a[j]+k*a[j^i]+p)%p;
}
}
if (t==2){// and
for (int i=1;i<=n;i<<=1){
for (int j=0;j<n;j+=(i<<1))
for (int _=0;_<i;_++){
a[j+_]=(a[j+_]+k*a[j+_+i]+p)%p;
}
}
}
if (t==3){// xor
for (int i=1;i<=n;i<<=1){
for (int j=0;j<n;j+=(i<<1))
for (int _=0;_<i;_++){
if (k==1){
X=a[j+_],Y=a[j+_+i];
a[j+_]=(X+Y)%p,a[j+_+i]=(X-Y+p)%p;
}
else{
X=a[j+_],Y=a[j+_+i];
a[j+_]=(X+Y)%p*inv%p,a[j+_+i]=(X-Y+p)%p*inv%p;
}
}
}
}
}
int main(){
scanf("%lld",&nn),n=1<<nn;
for (int i=0;i<n;i++) scanf("%lld",&a[i]);
for (int i=0;i<n;i++) scanf("%lld",&b[i]);
fwt(a,1,1),fwt(b,1,1);
for (int i=0;i<n;i++) c[i]=a[i]*b[i]%p;
fwt(a,1,-1),fwt(b,1,-1),fwt(c,1,-1);
for (int i=0;i<n;i++) printf("%lld ",c[i]);
printf("\n");
fwt(a,2,1),fwt(b,2,1);
for (int i=0;i<n;i++) c[i]=a[i]*b[i]%p;
fwt(a,2,-1),fwt(b,2,-1),fwt(c,2,-1);
for (int i=0;i<n;i++) printf("%lld ",c[i]);
printf("\n");
fwt(a,3,1),fwt(b,3,1);
for (int i=0;i<n;i++) c[i]=a[i]*b[i]%p;
fwt(a,3,-1),fwt(b,3,-1),fwt(c,3,-1);
for (int i=0;i<n;i++) printf("%lld ",c[i]*2%p);
printf("\n");
}
高斯消元
带模数版本
inline void gauss(int n)
{
for (int i=0;i<=n;i++){
int k=i,del,Inv;
for (int j=i+1;j<=n;j++) if (abs(a[j][i])>abs(a[k][i])) k=j;
if (a[k][i]==0) return;
if (k!=i) for (int j=i;j<=n+1;j++) swap(a[i][j],a[k][j]);
del=a[i][i];
Inv=qsm(del,mod-2);
for (int j=i;j<=n+1;j++) a[i][j]=1ll*a[i][j]*Inv%mod;
for (int k=0;k<=n;k++) if (k!=i){
int del=a[k][i];
for (int j=i;j<=n+1;j++) a[k][j]=(a[k][j]-1ll*del*a[i][j]%mod)%mod;
}
}
}
线性基
#include<bits/stdc++.h>
#define N 100050
using namespace std;
typedef long long ll;
ll p[64],a[N],n,ans;
inline void cal(ll x){
for (int i=62;i>=0;i--){
if (!(x&(1ll<<i))) continue;
if (!p[i]) {p[i]=x;break;}
x^=p[i];
}
}
int main(){
scanf("%lld",&n),ans=0ll;
for (int i=1;i<=n;i++) scanf("%lld",&a[i]),cal(a[i]);
for (int i=62;i>=0;i--) if ((ans^p[i])>ans) ans^=p[i];
printf("%lld\n",ans);
}
数据结构
LCT
其实我感觉不怎么能用上~
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define N 300050
using namespace std;
int w[N],n,m,x,y,opt;
struct lct
{
int s[N][2],f[N],lz[N],t[N],q[N],top;
inline bool isroot(int x) {return s[f[x]][0]!=x&&s[f[x]][1]!=x;}
inline void pushup(int x) {t[x]=t[s[x][0]]^t[s[x][1]]^w[x];}
inline void pushdown(int x) {if (lz[x]) lz[s[x][0]]^=1,lz[s[x][1]]^=1,lz[x]=0,swap(s[x][0],s[x][1]);}
inline void rotate(int x,int k)
{
int y=f[x],z=f[y];
s[y][!k]=s[x][k],f[x]=z;
if (s[x][k]) f[s[x][k]]=y;
if (!isroot(y)) s[z][y==s[z][1]]=x;
s[x][k]=y,f[y]=x,pushup(y),pushup(x);
}
inline void splay(int x)
{
top=0,q[++top]=x;
for (int i=x;!isroot(i);i=f[i]) q[++top]=f[i];
for (int i=top;i;i--) pushdown(q[i]);
while (!isroot(x))
{
int y=f[x],z=f[y];
if (isroot(y)) {rotate(x,x==s[y][0]);continue;}
if (y==s[z][0])
{
if (x==s[y][0]) rotate(y,1),rotate(x,1);
else rotate(x,0),rotate(x,1);
}
else
{
if (x==s[y][1]) rotate(y,0),rotate(x,0);
else rotate(x,1),rotate(x,0);
}
}
}
inline void access(int x) {for (int i=0;x;i=x,x=f[x]) splay(x),s[x][1]=i,pushup(x);}
inline void makeroot(int x) {access(x),splay(x),lz[x]^=1;}
inline int find(int x) {access(x),splay(x);while (s[x][0]) x=s[x][0];return x;}
inline void split(int x,int y){makeroot(x),access(y),splay(y);}
inline void cut(int x,int y) {split(x,y);if (x==s[y][0]) s[y][0]=0,f[x]=0;}
inline void link(int x,int y) {makeroot(x),f[x]=y;}
}T;
inline void read(int &x)
{
x=0;
int f=1;
char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
x=x*f;
}
int main()
{
read(n),read(m);
for (int i=1;i<=n;i++) read(w[i]),T.t[i]=w[i];
while (m--)
{
read(opt);
if (opt==0) read(x),read(y),T.split(x,y),printf("%d\n",T.t[y]);
if (opt==1) {read(x),read(y);if (T.find(x)!=T.find(y)) T.link(x,y);}
if (opt==2) {read(x),read(y);if (T.find(x)==T.find(y)) T.cut(x,y);}
if (opt==3) read(x),read(y),T.access(x),T.splay(x),w[x]=y,T.pushup(x);
}
return 0;
}
splay
操作大概是齐全了
struct node
{
int f,s[2],w,lz;
}a[maxn*2];
inline void rever(int l,int r)
{
l=kth(l),r=kth(r+2);
splay(l,0),splay(r,l);
a[a[a[root].s[1]].s[0]].lz^=1;
}
inline void rotate(int x,int k)
{
int y=a[x].f,z=a[y].f;
a[y].s[!k]=a[x].s[k];
if (a[y].s[!k]) a[a[y].s[!k]].f=y;
a[x].f=z;
if (z) a[z].s[y==a[z].s[1]]=x;
a[y].f=x,a[x].s[k]=y;
pushup(y),pushup(x);
}
inline void splay(int x,int g)
{
while (a[x].f!=g)
{
int y=a[x].f,z=a[y].f;
if (z==g) {rotate(x,a[y].s[0]==x);continue;}
if (y==a[z].s[0])
{
if (x==a[y].s[0]) rotate(y,1),rotate(x,1);
else rotate(x,0),rotate(x,1);
}
else
{
if (x==a[y].s[1]) rotate(y,0),rotate(x,0);
else rotate(x,1),rotate(x,0);
}
}
if (!g) root=x;
}
inline void del(int x)
{
splay(x);
if (a[x].s[0]==-1) {root=a[x].s[1],a[a[x].s[1]].f=-1;return;}
if (a[x].s[1]==-1) {root=a[x].s[0],a[a[x].s[0]].f=-1;return;}
int y=a[x].s[0];
while (a[y].s[1]!=-1) y=a[y].s[1];
a[a[x].s[0]].f=-1,splay(y),a[y].s[1]=a[x].s[1],a[a[x].s[1]].f=y,root=y;
}
inline void pre(int x)
{
tmp=root,p=-1,pnum=INF;
while (1)
{
if (tmp==-1) return;
if (a[tmp].w<x&&(x-a[tmp].w<pnum)) p=tmp,pnum=x-a[tmp].w;
if (a[tmp].w<x) tmp=a[tmp].s[1];else tmp=a[tmp].s[0];
}
}
inline void suc(int x)
{
tmp=root,q=-1,qnum=INF;
while (1)
{
if (tmp==-1) return;
if (a[tmp].w>x&&(a[tmp].w-x<pnum)) q=tmp,qnum=a[tmp].w-x;
if (a[tmp].w<x) tmp=a[tmp].s[1];else tmp=a[tmp].s[0];
}
}
inline int kth(int x)
{
int u=root;
while (1)
{
pushdown(u);
if (a[a[u].s[0]].sz>=x) u=a[u].s[0];
else if (a[a[u].s[0]].sz+1==x) return u;
else x-=a[a[u].s[0]].sz+1,u=a[u].s[1];
}
}
另外一种写法:
inline void upd(int x){a[x].sz=a[a[x].s[0]].sz+a[a[x].s[1]].sz+1;}
inline void link(int u,int v,int k) {a[v].f=u,a[u].s[k]=v;}
inline void rot(int x){
int u=a[x].f,k=(x==a[u].s[1]);
link(a[u].f,x,u==a[a[u].f].s[1]);
link(u,a[x].s[!k],k),link(x,u,!k);
upd(u),upd(x);
}
inline void splay(int x){
for (int u;u=a[x].f;rot(x)){
if (a[u].f&&(u==a[a[u].f].s[1])==(x==a[a[x].f].s[1])) rot(u);
}
root=x;
}
树链剖分
理解了很好写
louguP3384
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define N 200050
#define mid ((l+r)>>1)
#define add(u,v) to[++Top]=head[u],head[u]=Top,w[Top]=v
#define For(x) for(int h=head[x],o=w[h];h;o=w[h=to[h]])
using namespace std;
typedef long long ll;
int Top=0,to[N<<1],w[N<<1],head[N<<1];
int a[N],b[N],t[N<<3],tag[N<<3];
int son[N],mxson[N],sz[N],d[N],f[N],id[N],top[N];
int n,m,p,x,y,z,u,v,cnt=0,root,opt,ans;
template <class _T>inline void read(_T &x)
{
x=0;
char ch=getchar();
while (!isdigit(ch)) ch=getchar();
while (isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
}
inline void pushup(int x) {t[x]=(t[x<<1]+t[x<<1|1])%p;}
inline void pushdown(int x,int l,int r)
{
if (!tag[x]) return;
tag[x<<1]+=tag[x],tag[x<<1|1]+=tag[x];
t[x<<1]+=tag[x]*(mid-l+1),t[x<<1|1]+=tag[x]*(r-mid);
tag[x]=0;
}
void build(int x,int l,int r)
{
if (l==r) {t[x]=a[l]%p;return;}
build(x<<1,l,mid),build(x<<1|1,mid+1,r),pushup(x);
}
void upd(int x,int l,int r,int ql,int qr)
{
if (l==ql&&r==qr) {tag[x]+=z,t[x]=(t[x]+z*(r-l+1))%p;return;}
pushdown(x,l,r);
if (qr<=mid) upd(x<<1,l,mid,ql,qr);
else if (ql>mid) upd(x<<1|1,mid+1,r,ql,qr);
else upd(x<<1,l,mid,ql,mid),upd(x<<1|1,mid+1,r,mid+1,qr);
pushup(x);
}
int query(int x,int l,int r,int ql,int qr)
{
if (l==ql&&r==qr) return t[x]%p;
pushdown(x,l,r);
if (qr<=mid) return query(x<<1,l,mid,ql,qr);
else if (ql>mid) return query(x<<1|1,mid+1,r,ql,qr);
else return (query(x<<1,l,mid,ql,mid)+query(x<<1|1,mid+1,r,mid+1,qr))%p;
}
void dfs(int x,int fa)
{
d[x]=d[fa]+1,f[x]=fa,sz[x]=1,mxson[x]=-1;//深度,父结点,大小,重儿子大小
For(x) if (o!=fa)
{
dfs(o,x),sz[x]+=sz[o];
if (sz[o]>mxson[x]) son[x]=o,mxson[x]=sz[o];//重儿子
}
}
void dfs2(int x,int topf)//当前链最顶端结点
{
id[x]=++cnt,a[cnt]=b[x],top[x]=topf;//当前点重标号
if (!son[x]) return;
dfs2(son[x],topf);
For(x) if (o!=f[x]&&o!=son[x]) dfs2(o,o);
}
int main()
{
read(n),read(m),read(root),read(p);
for (int i=1;i<=n;i++) read(b[i]);
for (int i=1;i<n;i++) read(u),read(v),add(u,v),add(v,u);
dfs(root,0),dfs2(root,root),build(1,1,n);
while (m--)
{
read(opt);
if (opt==1)
{
read(x),read(y),read(z),z%=p;
while (top[x]!=top[y])
{
if (d[top[x]]<d[top[y]]) swap(x,y);
upd(1,1,n,id[top[x]],id[x]),x=f[top[x]];
}
if (d[x]<d[y]) swap(x,y);
upd(1,1,n,id[y],id[x]);
}
if (opt==2)
{
read(x),read(y),ans=0;
while (top[x]!=top[y])
{
if (d[top[x]]<d[top[y]]) swap(x,y);
ans=(ans+query(1,1,n,id[top[x]],id[x]))%p,x=f[top[x]];
}
if (d[x]<d[y]) swap(x,y);
ans=(ans+query(1,1,n,id[y],id[x]))%p,printf("%d\n",ans);
}
if (opt==3) read(x),read(z),upd(1,1,n,id[x],id[x]+sz[x]-1);
if (opt==4) read(x),printf("%d\n",query(1,1,n,id[x],id[x]+sz[x]-1));
}
}
主席树
#include<bits/stdc++.h>
#define N 200050
#define mid ((l+r)>>1)
using namespace std;
struct node{int l,r,sum;}T[N*19];
struct dat{
int x,n,w;
inline bool operator <(dat b) const{return x<b.x;}
}a[N];
inline bool cmp(dat p,dat q) {return p.n<q.n;}
int root[N],n,q,L,R,x,lim,tot=0,b[N];
inline void upd(int &x,int y,int pos,int l=0,int r=lim){
T[x=++tot]=T[y],T[x].sum=T[y].sum+1;
if (l==r) return;
if (pos<=mid) upd(T[x].l,T[y].l,pos,l,mid);else upd(T[x].r,T[y].r,pos,mid+1,r);
}
inline int query(int x,int y,int pos,int l=0,int r=lim){
if (l==r) return l;
if (T[T[y].l].sum-T[T[x].l].sum>=pos) return query(T[x].l,T[y].l,pos,l,mid);
else return query(T[x].r,T[y].r,pos-(T[T[y].l].sum-T[T[x].l].sum),mid+1,r);
}
int main(){
scanf("%d%d",&n,&q);
for (int i=1;i<=n;i++)
scanf("%d",&a[i].x),a[i].n=i;
sort(a+1,a+n+1);
for (int i=1;i<=n;i++) if (a[i].x==a[i-1].x) a[i].w=a[i-1].w;else a[i].w=a[i-1].w+1,b[a[i].w]=a[i].x;
lim=a[n].w,sort(a+1,a+n+1,cmp);
for (int i=1;i<=n;i++) upd(root[i],root[i-1],a[i].w);
while (q--){
scanf("%d%d%d",&L,&R,&x);
printf("%d\n",b[query(root[L-1],root[R],x)]);
}
}
树套树
施工中。。。
CDQ分治
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define N 200050
#define lowbit(x) (x&(-x))
#define fi first
#define se second
using namespace std;
typedef pair<int,int> pii;
int ans[N],n,k,t[N],p[N];
pii b[N];
struct xx
{
int x,y,z;
bool operator <(xx b)const
{
if (x!=b.x) return x<b.x;
if (y!=b.y) return y<b.y;
return z<b.z;
}
bool operator ==(xx b)const
{
if (x==b.x&&y==b.y&&z==b.z) return 1;
return 0;
}
}a[N];
inline void add(int x,int val) {while (x<=k) t[x]+=val,x+=lowbit(x);}
inline int query(int x)
{
int ret=0;
while (x>=1) ret+=t[x],x-=lowbit(x);
return ret;
}
template<class _T>inline void read(_T &x)
{
x=0;
char ch=getchar();
int f=0;
while (!isdigit(ch)) {if (ch=='-') f=1;ch=getchar();}
while (isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
if (f) x=-x;
}
inline void cdq(int l,int r)
{
if (l>=r) return;
int mid=(l+r)/2;
cdq(l,mid);
for (int i=l;i<=r;i++) b[i].fi=a[i].y,b[i].se=i;
sort(b+l,b+r+1); //y z
for (int i=l;i<=r;i++)
{
if (b[i].se==n) b[i].se=b[i].se;
if (b[i].se<=mid) add(a[b[i].se].z,1);else ans[b[i].se]+=query(a[b[i].se].z);
}
for (int i=l;i<=r;i++) if (b[i].se<=mid) add(a[b[i].se].z,-1);
cdq(mid+1,r);
}
int main()
{
read(n),read(k);
for (int i=1;i<=n;i++) read(a[i].x),read(a[i].y),read(a[i].z);
sort(a+1,a+n+1); //x y z
cdq(1,n);
for (int i=n-1;i>=1;i--) if (a[i]==a[i+1]) ans[i]=ans[i+1];
for (int i=1;i<=n;i++) p[ans[i]]++;
for (int i=0;i<n;i++) printf("%d\n",p[i]);
}
字符串
后缀数组
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1000050
char s[maxn];
int t[maxn],sa[maxn],x[maxn],y[maxn],p,m=128,n;
using namespace std;
int main()
{
scanf("%s",s),n=strlen(s),s[n++]=0;
for (int i=0;i<m;i++) t[i]=0;
for (int i=0;i<n;i++) t[x[i]=s[i]]++;
for (int i=1;i<m;i++) t[i]+=t[i-1];
for (int i=n-1;i>=0;i--) sa[--t[s[i]]]=i;
for (int j=1;p<n;j<<=1,m=p)
{
p=0;
for (int i=n-j;i<n;i++) y[p++]=i;
for (int i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j;
for (int i=0;i<m;i++) t[i]=0;
for (int i=0;i<n;i++) t[x[i]]++;
for (int i=1;i<m;i++) t[i]+=t[i-1];
for (int i=n-1;i>=0;i--) sa[--t[x[y[i]]]]=y[i];
swap(x,y),p=1;
x[sa[0]]=0;
for (int i=1;i<n;i++) if (y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]) x[sa[i]]=p-1;else x[sa[i]]=p++;
}
for (int i=1;i<n;i++) printf("%d ",sa[i]+1);
}
后缀自动机
应用较多,理解起来比较难
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define maxn 2000050
typedef long long ll;
using namespace std;
struct node
{
int f,len,go[30]; //father,length,edges
};
int sz[maxn],l,last,tot,c[maxn],a[maxn];
char s[maxn];
ll ans=0ll;
node t[maxn];
inline void extend(int c)
{
int now=++tot,p=last;
t[now].len=t[last].len+1;
for (;p!=-1&&t[p].go[c]==0;p=t[p].f) t[p].go[c]=now;
if (p==-1) t[now].f=0;
else
{
int q=t[p].go[c];
if (t[q].len==t[p].len+1) t[now].f=q;
else
{
int clone=++tot;
t[clone]=t[q],t[clone].len=t[p].len+1;
for (;p!=-1&&t[p].go[c]==q;p=t[p].f) t[p].go[c]=clone;
t[now].f=t[q].f=clone;
}
}
last=now,sz[now]=1;
}
inline void build()
{
scanf("%s",s+1),last=tot=0,t[0].f=-1,l=strlen(s+1);
for (int i=1;i<=l;i++) extend(s[i]-'a');
}
AC自动机
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define N 1000050
using namespace std;
int tot,go[160*80][28],fail[160*80],q[N],cnt[160],n,tmp[160];
char S[160][80],t[N];
struct res
{
int pos,num;
}val[160*80];
inline void build(char s[],int p)
{
int x=0,len=strlen(s);
for (int i=0;i<len;i++) if (go[x][s[i]-'a']) x=go[x][s[i]-'a'];else go[x][s[i]-'a']=++tot,x=tot;
if (val[x].pos) val[x].num++;else val[x].pos=p,val[x].num=1;
}
inline void init()
{
memset(go,0,sizeof(go)),memset(S,0,sizeof(S)),memset(fail,0,sizeof(fail));
memset(cnt,0,sizeof(cnt)),memset(val,0,sizeof(val)),tot=0;
}
inline void getfail(){
l=0,r=-1;
for (int i=0;i<26;i++) if (go[0][i]) q[++r]=go[0][i];
while (l<=r){
x=q[l++];
for (int i=0;i<26;i++) if (go[x][i]){
for (y=fail[x];y&&!go[y][i];y=fail[y]);
fail[q[++r]=go[x][i]]=go[y][i];
}
}
}
inline void query(char s[])
{
int x=0,len=strlen(s),ans=0;
for (int i=0;i<len;++i)
{
while (x&&(!go[x][s[i]-'a'])) x=fail[x];
x=go[x][s[i]-'a'];
if (val[x].pos) ++cnt[val[x].pos],tmp[val[x].pos]=val[x].num;
}
for (int i=1;i<=n;i++) ans=max(ans,cnt[i]);
printf("%d\n",ans);
for (int i=1;i<=n;i++) if (cnt[i]==ans) for (int j=1;j<=tmp[i];j++) printf("%s\n",S[i]);
}
int main()
{
while (1)
{
init(),scanf("%d",&n);
if (!n) return 0;
for (int i=1;i<=n;i++) scanf("%s",S[i]),build(S[i],i);
scanf("%s",t),getfail(),query(t);
}
}
图论
树的重心
算不上什么模板,点分治专用
inline void getroot(int x,int fa)
{
sz[x]=1,mxson[x]=0;
For(x) if (!vis[o]&&o!=fa)
{
getroot(o,x),sz[x]+=sz[o];
mxson[x]=max(mxson[x],sz[o]);
}
mxson[x]=max(tot-sz[x],mxson[x]);
if (mxson[x]<mx) mx=mxson[x],root=x;
}
inline void solve(int x)
{
vis[x]=1;
...
For(x) if (!vis[o])
{
tot=sz[o],root=0;
getroot(o,0),solve(o);
}
...
}
最小费用最大流
使用SPFA的EK算法
#include<bits/stdc++.h>
#define For(x) for(int h=head[x],o=w[h],c=cost[h];h;o=w[h=to[h]],c=cost[h])
#define add(u,v,vv,c) to[++top]=head[u],head[u]=top,w[top]=v,cap[top]=vv,cost[top]=c
#define N 100050
#define INF 1000000000
using namespace std;
int top=1,head[N],to[N],w[N],cap[N],cost[N];
int bo[N],dis[N],flow[N],q[N],pre[N],l,r,x;
int u,v,vv,c,n,m,ans=0,maxflow=0,s,t;
template<class _T>inline void read(_T &x)
{
x=0;
char ch=getchar();
while (!isdigit(ch)) ch=getchar();
while (isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
}
inline bool spfa(int s,int t)
{
memset(dis,0x7f7f7f,sizeof(dis)),memset(bo,0,sizeof(bo));
q[l=r=0]=s,bo[s]=1,dis[s]=0,flow[s]=INF;
while (l<=r)
{
x=q[l++],bo[x]=0;
For(x) if (cap[h]&&dis[o]>dis[x]+c)
{
dis[o]=dis[x]+c,flow[o]=min(flow[x],cap[h]);
pre[o]=h;
if (!bo[o]) q[++r]=o,bo[o]=1;
}
}
return dis[t]!=0x7f7f7f7f;
}
inline void upd(int s,int t)
{
int x=t;
while (x!=s)
{
int h=pre[x];
cap[h]-=flow[t],cap[h^1]+=flow[t];
x=w[h^1];
}
maxflow+=flow[t],ans+=flow[t]*dis[t];
}
inline void EK(int s,int t) {while (spfa(s,t)) upd(s,t);}
int main()
{
read(n),read(m),read(s),read(t);
while (m--) read(u),read(v),read(vv),read(c),add(u,v,vv,c),add(v,u,0,-c);
EK(s,t),printf("%d %d\n",maxflow,ans);;
}
Tarjan算法
#include<bits/stdc++.h>
#define N 100050
#define add(u,v) to[++top]=head[u],head[u]=top,w[top]=v
#define For(x) for(int h=head[x],o=w[h];h;o=w[h=to[h]])
using namespace std;
int n,m,u,v;
int top=0,head[N<<1],to[N<<1],w[N<<1];
int dfn[N],low[N],cut[N],tot=0,ans=0;
inline void tarjan(int x,int fa){
dfn[x]=low[x]=++tot;
int child=0;
For(x){
if (!dfn[o]){
tarjan(o,fa);
low[x]=min(low[x],low[o]);
if (low[o]>=dfn[x]&&x!=fa) cut[x]=1;
if (x==fa) child++;
}
low[x]=min(low[x],dfn[o]);
}
if (child>=2&&x==fa) cut[x]=1;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);
for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i,i);
for (int i=1;i<=n;i++) if (cut[i]) ans++;
printf("%d\n",ans);
for (int i=1;i<=n;i++) if (cut[i]) printf("%d ",i);
}
计算几何
凸包
Graham算法
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 10050
#define INF 10000050
using namespace std;
inline double cross(double p1,double p2,double p3,double p4) {return p1*p4-p2*p3;}
struct point
{
double x,y;
bool operator < (point q) const
{
if (x==0&&y==0) return 1;
if (q.x==0&&q.y==0) return 0;
return cross(q.x,q.y,x,y)<0;
}
}a[maxn],s[maxn];
int top=0,n,minid;
double ans=0,px,py;
inline double dis(point p,point q) {return (sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y)));}
double minx=INF;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
for (int i=1;i<=n;i++) if (a[i].x<minx) minx=a[i].x,minid=i;
px=a[minid].x,py=a[minid].y;
for (int i=1;i<=n;i++) a[i].x-=px,a[i].y-=py;
sort(a+1,a+n+1);
s[1]=a[1],s[2]=a[2],s[3]=a[3],top=3;
for (int i=4;i<=n;i++)
{
while (cross(a[i].x-s[top-1].x,a[i].y-s[top-1].y,a[i].x-s[top].x,a[i].y-s[top].y)<=0&&top>1) top--;
s[++top]=a[i];
}
for (int i=1;i<top;i++) ans+=dis(s[i],s[i+1]);
ans+=dis(s[1],s[top]);
printf("%.2f",ans);
}