板子
ST表
递推:f[i][j]=max(f[i][j-1],f[i+(1<<j)][j-1]
查询:max(f[l][x],f[r-(1<<x)+1][x])x=log2(r-l+1)
费用流
#include<bits/stdc++.h>
#define inf 2147483647
#define R register
using namespace std;
struct node
{
int to,val,next,flow;
}a[100005];
int n,m,S,T,x,y,z,v,q,ans,ans1,tot,head[5005],dis[5005];
bool bj[5005];
inline void add(int x,int y,int z,int v)
{
a[tot].to=y;
a[tot].flow=z;
a[tot].val=v;
a[tot].next=head[x];
head[x]=tot;
tot++;
}
inline bool OK()
{
int plus=inf;
for (R int i=1;i<=n;i++)
if (bj[i])
for (R int j=head[i];j!=-1;j=a[j].next)
if (!bj[a[j].to]&&a[j].flow) plus=min(plus,dis[a[j].to]+a[j].val-dis[i]);
if (plus==inf) return false;
for (R int i=1;i<=n;i++)
{
if (bj[i])
{
bj[i]=false;
dis[i]+=plus;
}
}
return true;
}
inline int mnmx(int now,int sum)
{
if (now==T)
{
ans1+=dis[S]*sum;
return sum;
}
bj[now]=true;
int x,u;
for (R int i=head[now];i!=-1;i=a[i].next)
{
u=a[i].to;
if (!bj[u]&&dis[u]+a[i].val==dis[now]&&a[i].flow)
{
x=mnmx(u,min(sum,a[i].flow));
if (x)
{
a[i].flow-=x;
a[i^1].flow+=x;
return x;
}
}
}
return 0;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&S,&T);
for (R int i=1;i<=n;i++)
head[i]=-1;
for (R int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x,&y,&z,&v);
add(x,y,z,v);
add(y,x,0,-v);
}
bj[S]=true;
while (OK())
{
q=mnmx(S,inf);
while (q)
{
ans+=q;
memset(bj,false,sizeof(bj));
q=mnmx(S,inf);
}
}
printf("%d %d\n",ans,ans1);
return 0;
}
无旋treap
#include<cstdio>
#include<stdlib.h>
using namespace std;
int n,pd,x,size[100005],rd[100005],val[100005],son[100005][3],root,tot;
void pushup(int x)
{
size[x]=size[son[x][0]]+size[son[x][1]]+1;
}
int makenum(int v)
{
tot++;
son[tot][0]=son[tot][1]=0;
rd[tot]=rand();
val[tot]=v;
size[tot]=1;
return tot;
}
void split(int now,int v,int &x,int &y)
{
if (!now)
{
x=y=0;
return;
}
if (val[now]<=v)
{
x=now;
split(son[now][1],v,son[now][1],y);
pushup(x);
}
else
{
y=now;
split(son[now][0],v,x,son[now][0]);
pushup(y);
}
}
int merge(int x,int y)
{
if (!x||!y) return x+y;
if (rd[x]>rd[y])
{
son[x][1]=merge(son[x][1],y);
pushup(x);
return x;
}
else
{
son[y][0]=merge(x,son[y][0]);
pushup(y);
return y;
}
}
void ins(int v)
{
int x,y;
split(root,v,x,y);
root=merge(merge(x,makenum(v)),y);
}
void del(int v)
{
int x,y,z;
split(root,v-1,x,y);
split(y,v,y,z);
y=merge(son[y][0],son[y][1]);
root=merge(merge(x,y),z);
}
int get_rank(int v)
{
int x,y;
split(root,v-1,x,y);
int ans=size[x]+1;
root=merge(x,y);
return ans;
}
int get_sum(int now,int v)
{
if (v<=size[son[now][0]]) return get_sum(son[now][0],v);
if (v<=size[son[now][0]]+1) return now;
else return get_sum(son[now][1],v-size[son[now][0]]-1);
}
int get_pre(int v)
{
int x,y;
split(root,v-1,x,y);
int ans=val[get_sum(x,size[x])];
root=merge(x,y);
return ans;
}
int get_suc(int v)
{
int x,y;
split(root,v,x,y);
int ans=val[get_sum(y,1)];
root=merge(x,y);
return ans;
}
int main()
{
scanf("%d",&n);
while (n--)
{
scanf("%d%d",&pd,&x);
if (pd==1) ins(x);
if (pd==2) del(x);
if (pd==3) printf("%d\n",get_rank(x));
if (pd==4) printf("%d\n",val[get_sum(root,x)]);
if (pd==5) printf("%d\n",get_pre(x));
if (pd==6) printf("%d\n",get_suc(x));
}
return 0;
}
SA(后缀数组)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1000005
using namespace std;
int all=122,n,num,fir[N],t[N],sec[N],sa[N];
char s[N];
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
for (int i=1;i<=n;++i)
fir[i]=s[i],t[fir[i]]++;
for (int i=1;i<=all;++i)
t[i]+=t[i-1];
for (int i=n;i;--i)
sa[t[fir[i]]--]=i;
for (int k=1;k<=n;k<<=1)
{
num=0;
for (int i=n-k+1;i<=n;++i)
sec[++num]=i;
for (int i=1;i<=n;++i)
if (sa[i]>k) sec[++num]=sa[i]-k;
for (int i=1;i<=all;++i)
t[i]=0;
for (int i=1;i<=n;++i)
++t[fir[i]];
for (int i=1;i<=all;++i)
t[i]+=t[i-1];
for (int i=n;i;--i)
sa[t[fir[sec[i]]]--]=sec[i],sec[i]=0;
swap(fir,sec);
fir[sa[1]]=1;
num=1;
for (int i=2;i<=n;++i)
{
if (sec[sa[i]]==sec[sa[i-1]]&&sec[sa[i]+k]==sec[sa[i-1]+k]) fir[sa[i]]=num;
else fir[sa[i]]=++num;
}
if (num==n) break;
all=num;
}
for (int i=1;i<=n;++i)
printf("%d ",sa[i]);
return 0;
}
三维偏序(cdq分治)
#include<cstdio>
#include<algorithm>
#define N 200005
using namespace std;
struct node
{
int a,b,c,ans,cnt;
}q[N],p[N];
int n,k,m,num,tr[N<<2],ans[N];
int lowbit(int x) {return x&(-x);}
bool cmp1(node x,node y)
{
if (x.a<y.a) return true;
if (x.a>y.a) return false;
if (x.b==y.b) return x.c<y.c;
else return x.b<y.b;
}
bool cmp2(node x,node y)
{
if (x.b<y.b) return true;
if (x.b>y.b) return false;
return x.c<y.c;
}
void add(int x,int y)
{
for (;x<=k;x+=lowbit(x)) tr[x]+=y;
}
int query(int x)
{
int res=0;
for (;x;x-=lowbit(x)) res+=tr[x];
return res;
}
void cdq(int l,int r)
{
if (l==r) return;
int mid=(l+r)>>1;
cdq(l,mid);cdq(mid+1,r);
sort(p+l,p+mid+1,cmp2);sort(p+mid+1,p+r+1,cmp2);
int i,j=l;
for (int i=mid+1;i<=r;++i)
{
while (p[i].b>=p[j].b&&j<=mid)
{
add(p[j].c,p[j].cnt);
j++;
}
p[i].ans+=query(p[i].c);
}
for (int i=l;i<j;++i)
add(p[i].c,-p[i].cnt);
}
int main()
{
scanf("%d%d",&n,&k);
for (int i=1;i<=n;++i)
scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].c);
sort(q+1,q+n+1,cmp1);
for (int i=1;i<=n;++i)
{
++num;
if (q[i].a!=q[i+1].a||q[i].b!=q[i+1].b||q[i].c!=q[i+1].c)
{
p[++m].a=q[i].a;p[m].b=q[i].b;p[m].c=q[i].c;
p[m].cnt=num;num=0;
}
}
cdq(1,m);
for (int i=1;i<=n;++i)
ans[p[i].ans+p[i].cnt-1]+=p[i].cnt;
for (int i=0;i<n;++i)
printf("%d\n",ans[i]);
return 0;
}
主席树
#include<cstdio>
#include<algorithm>
#define N 200005
using namespace std;
struct node
{
int rt,lson,rson,sum;
}tr[N<<5];
int n,m,q,p,l,r,k,ans,cnt,a[N],b[N];
void build(int &root,int l,int r)
{
root=++cnt;
if (l==r) return;
int mid=(l+r)>>1;
build(tr[root].lson,l,mid);
build(tr[root].rson,mid+1,r);
}
int modify(int now,int l,int r)
{
int nxt=++cnt;
tr[nxt].lson=tr[now].lson;
tr[nxt].rson=tr[now].rson;
tr[nxt].sum=tr[now].sum+1;
if (l==r) return nxt;
int mid=(l+r)>>1;
if (p<=mid) tr[nxt].lson=modify(tr[nxt].lson,l,mid);
else tr[nxt].rson=modify(tr[nxt].rson,mid+1,r);
return nxt;
}
int query(int u,int v,int l,int r,int k)
{
int res=0,mid=(l+r)>>1,x=tr[tr[v].lson].sum-tr[tr[u].lson].sum;
if (l==r) return l;
if (x>=k) res=query(tr[u].lson,tr[v].lson,l,mid,k);
else res=query(tr[u].rson,tr[v].rson,mid+1,r,k-x);
return res;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i)
scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
q=unique(b+1,b+n+1)-b-1;
build(tr[0].rt,1,q);
for (int i=1;i<=n;++i)
{
p=lower_bound(b+1,b+q+1,a[i])-b;
tr[i].rt=modify(tr[i-1].rt,1,q);
}
while (m--)
{
scanf("%d%d%d",&l,&r,&k);
ans=query(tr[l-1].rt,tr[r].rt,1,q,k);
printf("%d\n",b[ans]);
}
return 0;
}
FFT
#include <bits/stdc++.h>
const int NR = 1 << 22;
const double eps = 0.49, pi = acos(-1.0);
using namespace std;
complex<double> a[NR];
int n, m, rev[NR];
void FFT(complex<double> *a, int n, int inv)
{
for (int i = 0; i < n; ++i)
if (i < rev[i])
swap(a[i], a[rev[i]]);
for (int i = 1; i < n; i <<= 1)
{
complex<double> wn(cos(pi / i), inv * sin(pi / i));
for (int j = 0; j < n; j += (i << 1))
{
complex<double> w0(1, 0);
for (int k = 0; k < i; ++k, w0 *= wn)
{ //??
complex<double> x = a[j + k], y = w0 * a[i + j + k];
a[j + k] = x + y;
a[i + j + k] = x ## y;
}
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i <= n; ++i)
{
double x;
scanf("%lf", &x);
a[i].real(x);
}
for (int i = 0; i <= m; ++i)
{
double x;
scanf("%lf", &x);
a[i].imag(x);
}
int len = 1 << max((int)ceil(log2(n + m)), 1);
for (int i = 0; i < len; ++i)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (max((int)ceil(log2(n + m)), 1) ## 1));
FFT(a, len, 1);
for (int i = 0; i <= len; ++i)
a[i] = a[i] * a[i];
FFT(a, len, -1);
for (int i = 0; i <= n + m; ++i)
printf("%.0f ", a[i].imag() / 2 / len + eps);
return 0;
}
KMP
#include<cstdio>
#include<cstring>
#define N 1000005
using namespace std;
int n,m,p[N<<1];
char s[N<<1],s1[N],s2[N];
int main()
{
scanf("%s",s1+1);scanf("%s",s2+1);
n=strlen(s1+1);m=strlen(s2+1);
for (int i=1;i<=m;++i)
s[i]=s2[i];
s[m+1]='#';
for (int i=1;i<=n;++i)
s[m+i+1]=s1[i];
for (int i=2;i<=n+m+1;++i)
{
int j=p[i-1];
while (j>0&&s[i]!=s[j+1]) j=p[j];
if (s[i]==s[j+1]) j++;
p[i]=j;
}
for (int i=m+2;i<=n+m+1;++i)
if (p[i]==m) printf("%d\n",i-2*m);
for (int i=1;i<=m;++i)
printf("%d ",p[i]);
return 0;
}
Dinic
#include<queue>
#include<cstdio>
#include<cstring>
#define N 205
#define M 5005
#define inf 12345645656879
#define ll long long
using namespace std;
int n,m,s,t,tot=1,dep[N],cur[N];
ll ans;
struct node {int to,next,head;ll flow;}a[M<<1];
queue<int> q;
ll min(ll x,ll y) {return x<y?x:y;}
void add(int x,int y,ll z)
{
a[++tot].to=y;a[tot].flow=z;a[tot].next=a[x].head;a[x].head=tot;
a[++tot].to=x;a[tot].flow=0;a[tot].next=a[y].head;a[y].head=tot;
}
bool bfs()
{
memset(dep,0,sizeof(dep));
for (int i=1;i<=n;++i)
cur[i]=a[i].head;
dep[s]=1;
while (!q.empty()) q.pop();
q.push(s);
while (!q.empty())
{
int x=q.front();q.pop();
for (int i=a[x].head;i;i=a[i].next)
{
int y=a[i].to;ll z=a[i].flow;
if (z&&!dep[y])
{
dep[y]=dep[x]+1;
q.push(y);
if (y==t) return true;
}
}
}
return false;
}
ll dinic(int x,ll f)
{
if (x==t) return f;
ll sum=0;
for (int i=cur[x];i;i=a[i].next)
{
cur[x]=i;
int y=a[i].to;ll z=a[i].flow;
if (z&&dep[y]==dep[x]+1)
{
ll res=dinic(y,min(f,z));
a[i].flow-=res;a[i^1].flow+=res;
sum+=res;f-=res;
if (f<=0) break;
}
}
return sum;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=1;i<=m;++i)
{
int x,y;ll z;
scanf("%d%d%lld",&x,&y,&z);
add(x,y,z);
}
while (bfs()) ans+=dinic(s,inf);
printf("%lld\n",ans);
return 0;
}
线性筛(素数、欧拉数、莫比乌斯函数)
phi[1]=1;
for (int i=2;i<=N;++i)
{
if (!phi[i]) p[++prt]=i,phi[i]=i-1,mu[i]=-1;
for (int j=1;j<=prt&&i*p[j]<=N;++j)
{
if (i*%pri[j]==0) {phi[i*p[j]]=phi[i]*p[j];mu[i*p[j]]=0;break;}
phi[i*p[j]]=phi[i]*phi[p[j]];
mu[i*p[j]]=-mu[i];
}
}
向量旋转
将一个向量逆时针旋转任意角 \(\theta\),就是乘矩阵 \(\begin{vmatrix}\cos \theta&-\sin \theta\\\sin \theta & \cos \theta\end{vmatrix}\)。

浙公网安备 33010602011771号