模板

数据结构

单调队列

// BZOJ 2096
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 3000005

int k,n,l,r,lmax,rmax,lmin,rmin,ans;
int a[N],qmax[N],qmin[N];
struct hp{int Max,Min;};

void push(int id)
{
while (lmax<rmax&&a[qmax[rmax]]<=a[id]) --rmax;
qmax[++rmax]=id;
while (lmin<rmin&&a[qmin[rmin]]>=a[id]) --rmin;
qmin[++rmin]=id;
}
hp pop(int id)
{
while (lmax<rmax&&qmax[lmax+1]<id) ++lmax;
int Max=a[qmax[lmax+1]];
while (lmin<rmin&&qmin[lmin+1]<id) ++lmin;
int Min=a[qmin[lmin+1]];
return (hp){Max,Min};
}
int main()
{
scanf("%d%d",&k,&n);
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
l=r=1;lmax=rmax=lmin=rmin=0;push(l);
while (l<=n)
{
if (l>r)
{
r=l;lmax=rmax=lmin=rmin=0;push(l);
}
while (r<n)
{
hp now=pop(l);
if (a[r+1]>now.Max)
{if (a[r+1]-now.Min>k) break;}
else if (a[r+1]<now.Min)
{if (now.Max-a[r+1]>k) break;}
++r;push(r);
}
ans=max(ans,r-l+1);
++l;
}
printf("%d\n",ans);
}

单调栈

// BZOJ 1657
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 50005

int n,h[N],val[N],l[N],r[N],Max,stack[N],top,sum[N],ans;

int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d%d",&h[i],&val[i]),l[i]=1,r[i]=n;

top=0;
for (int i=1;i<=n;++i)
{
while (top&&h[stack[top]]<h[i])
{
r[stack[top]]=i-1;
--top;
}
stack[++top]=i;
}
top=0;
for (int i=n;i>=1;--i)
{
while (top&&h[stack[top]]<h[i])
{
l[stack[top]]=i+1;
--top;
}
stack[++top]=i;
}
for (int i=1;i<=n;++i) sum[l[i]-1]+=val[i],sum[r[i]+1]+=val[i];
for (int i=1;i<=n;++i) ans=max(ans,sum[i]);
printf("%d\n",ans);
}

St表

// poj3264
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define N 50005
#define sz 16
using namespace std;
int n,m,l,r,Max,Min;
int a[N],lg2[N],stmax[N][sz],stmin[N][sz];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1,p=0;i<=n;++i)
{
while ((1<<p)<=i) ++p;
lg2[i]=p-1;
}
for (int i=1;i<=n;++i)
scanf("%d",&a[i]),stmax[i][0]=stmin[i][0]=a[i];
for (int j=1;j<sz;++j)
for (int i=1;i<=n;++i)
if (i+(1<<j)-1<=n)
{
stmax[i][j]=max(stmax[i][j-1],stmax[i+(1<<(j-1))][j-1]);
stmin[i][j]=min(stmin[i][j-1],stmin[i+(1<<(j-1))][j-1]);
}
for (int i=1;i<=m;++i)
{
scanf("%d%d",&l,&r);
if (l>r) swap(l,r);
int k=lg2[r-l+1];
Max=max(stmax[l][k],stmax[r-(1<<k)+1][k]);
Min=min(stmin[l][k],stmin[r-(1<<k)+1][k]);
printf("%d\n",Max-Min);
}
}

Lca

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 100005
#define sz 17

int n,m,x,y;
int tot,point[N],nxt[N*2],v[N*2];
int f[N][sz+5],h[N],size[N];
struct hp{int pre,pt;};

{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void build(int x,int fa,int dep)
{
h[x]=dep; size[x]=1;
for (int i=1;i<sz;++i)
{
if ((h[x]-(1<<i))<1) break;
f[x][i]=f[f[x][i-1]][i-1];
}
for (int i=point[x];i;i=nxt[i])
if (v[i]!=fa)
{
f[v[i]][0]=x;
build(v[i],x,dep+1);
size[x]+=size[v[i]];
}
}
int lca(int x,int y)
{
if (h[x]<h[y]) swap(x,y);
int k=h[x]-h[y];
for (int i=0;i<sz;++i)
if ((1<<i)&k) x=f[x][i];
if (x==y) return x;
for (int i=sz-1;i>=0;--i)
if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
hp find(int x,int high)
{
int xx=x;
for (int i=sz-1;i>=0;--i)
while (h[f[x][i]]>high) xx=x,x=f[x][i];
xx=x,x=f[x][0];
hp ans;ans.pre=xx,ans.pt=x;
return ans;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
}
build(1,0,1);
scanf("%d",&m);
for (int i=1;i<=m;++i)
{
scanf("%d%d",&x,&y);
if (h[x]<h[y]) swap(x,y);
if (x==y)
{
printf("%d\n",n);
continue;
}
int r=lca(x,y);
int len=h[x]-h[r]+h[y]-h[r];
if (len%2)
{
puts("0");
continue;
}
len/=2;
int high=h[x]-len;
if (high==h[r])
{
hp date1=find(x,high);
hp date2=find(y,high);
printf("%d\n",n-size[r]+size[r]-size[date1.pre]-size[date2.pre]);
}
else
{
hp date=find(x,high);
printf("%d\n",size[date.pt]-size[date.pre]);
}
}
}

Splay

// BZOJ 3224
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 300005

int n,opt,x,root,sz;
int f[N],ch[N][2],key[N],size[N],cnt[N];

void clear(int x)
{
f[x]=ch[x][0]=ch[x][1]=key[x]=size[x]=cnt[x]=0;
}
int get(int x)
{
return ch[f[x]][1]==x;
}
void update(int x)
{
size[x]=cnt[x]+size[ch[x][0]]+size[ch[x][1]];
}
void rotate(int x)
{
int old=f[x],oldf=f[old],wh=get(x);
ch[old][wh]=ch[x][wh^1];
if (ch[old][wh]) f[ch[old][wh]]=old;
ch[x][wh^1]=old;
f[old]=x;
if (oldf) ch[oldf][ch[oldf][1]==old]=x;
f[x]=oldf;
update(old);
update(x);
}
void splay(int x)
{
for (int fa;fa=f[x];rotate(x))
if (f[fa])
rotate( (get(x)==get(fa))?fa:x );
root=x;
}
void insert(int x)
{
if (!root)
{
root=++sz;
cnt[sz]=size[sz]=1;key[sz]=x;
return;
}
int now=root,fa=0;
while (1)
{
if (x==key[now])
{
cnt[now]++;
update(now);
splay(now);
break;
}
fa=now;
now=ch[now][x>key[now]];
if (!now)
{
++sz;
f[sz]=fa;ch[fa][x>key[fa]]=sz;
size[sz]=cnt[sz]=1;
key[sz]=x;
update(fa);
splay(sz);
break;
}
}
}
int find(int x)
{
int now=root,ans=0;
while (1)
{
if (x<key[now]) now=ch[now][0];
else
{
ans+=size[ch[now][0]];
if (x==key[now])
{
splay(now);
return ans+1;
}
ans+=cnt[now];
now=ch[now][1];
}
}
}
int findx(int x)
{
int now=root;
while (1)
{
if (x<=size[ch[now][0]]) now=ch[now][0];
else
{
x-=size[ch[now][0]];
if (x<=cnt[now])
{
splay(now);
return key[now];
}
x-=cnt[now];
now=ch[now][1];
}
}
}
int pre()
{
int now=ch[root][0];
while (ch[now][1]) now=ch[now][1];
return now;
}
int nxt()
{
int now=ch[root][1];
while (ch[now][0]) now=ch[now][0];
return now;
}
void del(int x)
{
int wh=find(x);
if (cnt[root]>1)
{
--cnt[root];
update(root);
return;
}
if (!ch[root][0]&&!ch[root][1])
{
clear(root);
root=0;
return;
}
if (!ch[root][0])
{
int oldroot=root;
root=ch[oldroot][1];
f[root]=0;
clear(oldroot);
return;
}
if (!ch[root][1])
{
int oldroot=root;
root=ch[oldroot][0];
f[root]=0;
clear(oldroot);
return;
}
int oldroot=root;
int leftbig=pre();splay(leftbig);
ch[root][1]=ch[oldroot][1];
f[ch[root][1]]=root;
clear(oldroot);
update(root);
return;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i)
{
scanf("%d%d",&opt,&x);
switch(opt)
{
case 1:
{
insert(x);
break;
}
case 2:
{
del(x);
break;
}
case 3:
{
int ans=find(x);
printf("%d\n",ans);
break;
}
case 4:
{
int ans=findx(x);
printf("%d\n",ans);
break;
}
case 5:
{
insert(x);
printf("%d\n",key[pre()]);
del(x);
break;
}
case 6:
{
insert(x);
printf("%d\n",key[nxt()]);
del(x);
break;
}
}
}
return 0;
}
// BZOJ 3223
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 100005
#define inf 1000000000

int n,m,l,r,root;
int a[N],f[N],ch[N][2],size[N],key[N],delta[N];

int get(int x)
{
return ch[f[x]][1]==x;
}
void update(int x)
{
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void pushdown(int x)
{
if (x&&delta[x])
{
delta[ch[x][0]]^=1;
delta[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
delta[x]=0;
}
}
int build(int l,int r,int fa)
{
if (l>r) return 0;
int mid=(l+r)>>1;
f[mid]=fa;key[mid]=a[mid];size[mid]=1;
int lch=build(l,mid-1,mid);
int rch=build(mid+1,r,mid);
ch[mid][0]=lch,ch[mid][1]=rch;
update(mid);
return mid;
}
void rotate(int x)
{
pushdown(f[x]);
pushdown(x);
int old=f[x],oldf=f[old],wh=get(x);
ch[old][wh]=ch[x][wh^1];
if (ch[old][wh]) f[ch[old][wh]]=old;
ch[x][wh^1]=old;
f[old]=x;
if (oldf) ch[oldf][ch[oldf][1]==old]=x;
f[x]=oldf;
update(old);
update(x);
}
void splay(int x,int tar)
{
for (int fa;(fa=f[x])!=tar;rotate(x))
if (f[fa]!=tar)
rotate( (get(x)==get(fa))?fa:x );
if (!tar) root=x;
}
int find(int x)
{
int now=root;
while (1)
{
pushdown(now);
if (x<=size[ch[now][0]]) now=ch[now][0];
else
{
x-=size[ch[now][0]];
if (x==1) return now;
x-=1;
now=ch[now][1];
}
}
}
void write(int x)
{
pushdown(x);
if (ch[x][0]) write(ch[x][0]);
if (key[x]!=-inf&&key[x]!=inf) printf("%d ",key[x]);
if (ch[x][1]) write(ch[x][1]);
}
int main()
{
scanf("%d%d",&n,&m);
a[1]=-inf;a[n+2]=inf;
for (int i=1;i<=n;++i) a[i+1]=i;
root=build(1,n+2,0);
for (int i=1;i<=m;++i)
{
scanf("%d%d",&l,&r);
if (l>=r) continue;
int aa=find(l);
int bb=find(r+2);
splay(aa,0);
splay(bb,aa);
delta[ch[ch[root][1]][0]]^=1;
}
write(root);
return 0;
}

树链剖分+dfs序

// BZOJ4196 NOI2015 软件包管理器
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int max_n=1e5+5;
const int max_e=max_n*2;
const int max_tree=max_n*5;

int n,q,x,N,ans;
char s[20];
int tot,point[max_n],next[max_e],v[max_e];
int size[max_n],h[max_n],father[max_n],son[max_n];
int top[max_n],in[max_n],out[max_n];
int sum[max_tree],delta[max_tree];

++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x;
}

inline void dfs_1(int x,int fa,int dep){
size[x]=1; h[x]=dep; father[x]=fa;
int maxson=0;

for (int i=point[x];i;i=next[i])
if (v[i]!=fa){
dfs_1(v[i],x,dep+1);
size[x]+=size[v[i]];
if (maxson<size[v[i]]){
maxson=size[v[i]];
son[x]=v[i];
}
}
}

inline void dfs_2(int x,int fa){
if (son[fa]!=x) top[x]=x;
else top[x]=top[fa];
in[x]=++N;

if (son[x]) dfs_2(son[x],x);
for (int i=point[x];i;i=next[i])
if (v[i]!=fa&&v[i]!=son[x])
dfs_2(v[i],x);

out[x]=N;
}

inline void update(int now){
sum[now]=sum[now<<1]+sum[now<<1|1];
}

inline void pushdown(int now,int l,int r,int mid){
if (delta[now]>=0){
sum[now<<1]=delta[now]*(mid-l+1);
delta[now<<1]=delta[now];
sum[now<<1|1]=delta[now]*(r-mid);
delta[now<<1|1]=delta[now];
delta[now]=-1;
}
}

inline void interval_change(int now,int l,int r,int lrange,int rrange,int v){
int mid=(l+r)>>1;
if (lrange<=l&&r<=rrange){
sum[now]=(r-l+1)*v;
delta[now]=v;
return;
}

pushdown(now,l,r,mid);
if (lrange<=mid)
interval_change(now<<1,l,mid,lrange,rrange,v);
if (mid+1<=rrange)
interval_change(now<<1|1,mid+1,r,lrange,rrange,v);
update(now);
}

inline int query(int now,int l,int r,int lrange,int rrange){
int mid=(l+r)>>1,ans=0;
if (lrange<=l&&r<=rrange) return sum[now];

pushdown(now,l,r,mid);
if (lrange<=mid)
ans+=query(now<<1,l,mid,lrange,rrange);
if (mid+1<=rrange)
ans+=query(now<<1|1,mid+1,r,lrange,rrange);
return ans;
}

inline void QUERY(int u,int t){
int f1=top[u],f2=top[t],ans=0;
while (f1!=f2){
if (h[f1]<h[f2]){
swap(f1,f2);
swap(u,t);
}
ans+=query(1,1,N,in[f1],in[u]);
u=father[f1];
f1=top[u];
}
if (in[u]>in[t]) swap(u,t);
ans+=query(1,1,N,in[u],in[t]);
int cnt=h[x];
printf("%d\n",cnt-ans);
}

inline void CHANGE(int u,int t){
int f1=top[u],f2=top[t],ans=0;
while (f1!=f2){
if (h[f1]<h[f2]){
swap(f1,f2);
swap(u,t);
}
interval_change(1,1,N,in[f1],in[u],1);
u=father[f1];
f1=top[u];
}
if (in[u]>in[t]) swap(u,t);
interval_change(1,1,N,in[u],in[t],1);
}

inline void INSTALL(int u,int t){
QUERY(u,t);
CHANGE(u,t);
}

inline void UNINSTALL(int x){
ans=query(1,1,N,in[x],out[x]);
printf("%d\n",ans);

interval_change(1,1,N,in[x],out[x],0);
}

int main(){
scanf("%d",&n);
for (int i=1;i<n;++i){
scanf("%d",&x);
++x;
}

dfs_1(1,0,1);
dfs_2(1,0);

memset(sum,0,sizeof(sum));
memset(delta,128,sizeof(delta));

scanf("%d",&q);
for (int i=1;i<=q;++i){
scanf("%s",s);
scanf("%d",&x);
++x;
if (s[0]=='i')
INSTALL(1,x);
else
UNINSTALL(x);
}
}

手写栈

inline void dfs_1()
{
int temp=0;
strack[++temp]=1; size[1]=1; h[1]=1;
for (int i=1;i<=n;++i) cur[i]=point[i];
while (temp)
{
int x=strack[temp];
if (v[cur[x]]==father[x]) cur[x]=nxt[cur[x]];
if (!cur[x])
{
temp--;
if (father[x])
{
size[father[x]]+=size[x];
if (size[x]>size[son[father[x]]]) son[father[x]]=x;
}
continue;
}
int vt=v[cur[x]];
strack[++temp]=vt;
size[vt]=1; h[vt]=h[x]+1; father[vt]=x;
cur[x]=nxt[cur[x]];
}
}
inline void dfs_2()
{
int temp=0;
strack[++temp]=1; num[1]=++N; top[1]=1;
for (int i=1;i<=n;++i) cur[i]=point[i];
while (temp)
{
int x=strack[temp];
if (!use[x])
{
use[x]=1;
int vt=son[x];
if (vt)
{
strack[++temp]=vt;
top[vt]=top[x];
num[vt]=++N;
}
continue;
}
while (cur[x]&&(v[cur[x]]==father[x]||v[cur[x]]==son[x])) cur[x]=nxt[cur[x]];
if (!cur[x])
{
temp--;
continue;
}
else
{
int vt=v[cur[x]];
strack[++temp]=vt;
top[vt]=vt;
num[vt]=++N;
cur[x]=nxt[cur[x]];
}
}
}
// BZOJ2049
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 10005

char opt[10];
int n,m;
int f[N],ch[N][2],rev[N],stack[N];

bool isroot(int x)
{
return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;
}
int get(int x)
{
return ch[f[x]][1]==x;
}
void pushdown(int x)
{
if (x&&rev[x])
{
if (ch[x][0]) rev[ch[x][0]]^=1;
if (ch[x][1]) rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
}
void rotate(int x)
{
int old=f[x],oldf=f[old],wh=get(x);
if (!isroot(old)) ch[oldf][ch[oldf][1]==old]=x;
f[x]=oldf;
ch[old][wh]=ch[x][wh^1];
if (ch[old][wh]) f[ch[old][wh]]=old;
ch[x][wh^1]=old;
f[old]=x;
}
void splay(int x)
{
int top=0;stack[++top]=x;
for (int i=x;!isroot(i);i=f[i]) stack[++top]=f[i];
for (int i=top;i>=1;--i) pushdown(stack[i]);

for (int fa;!isroot(x);rotate(x))
if (!isroot(fa=f[x]))
rotate((get(x)==get(fa))?fa:x);
}
void access(int x)
{
int t=0;
for (;x;t=x,x=f[x])
{
splay(x);
ch[x][1]=t;
}
}
void reverse(int x)
{
access(x);
splay(x);
rev[x]^=1;
}
{
reverse(x);
f[x]=y;
}
void cut(int x,int y)
{
reverse(x);
access(y);
splay(y);
f[x]=ch[y][0]=0;
}
int find(int x)
{
access(x);
splay(x);
while (ch[x][0]) x=ch[x][0];
return x;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
scanf("%s",opt);
int x,y;scanf("%d%d",&x,&y);
if (opt[0]=='C')
else if (opt[0]=='D')
cut(x,y);
else
{
if (find(x)==find(y)) puts("Yes");
else puts("No");
}
}
}

静态主席树

// POJ 2104 K-th Number
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int max_n=1e5+5;

int n,m,x,y,z,sz,ans;
int val[max_n],p[max_n],num[max_n],root[max_n];
int sum[max_n*20],ls[max_n*20],rs[max_n*20];

inline int cmp(int a,int b){return val[a]<val[b];}
inline void build(int &now,int l,int r,int x){
int mid=(l+r)>>1;
sum[++sz]=sum[now]; ls[sz]=ls[now]; rs[sz]=rs[now];
now=sz;
++sum[now];
if (l==r) return;
if (x<=mid) build(ls[now],l,mid,x);
else build(rs[now],mid+1,r,x);
}
inline int query(int i,int j,int l,int r,int k){
int mid=(l+r)>>1;
if (l==r) return l;
int t=sum[ls[j]]-sum[ls[i]];
if (t>=k) return query(ls[i],ls[j],l,mid,k);
else return query(rs[i],rs[j],mid+1,r,k-t);
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d",&val[i]),p[i]=i;
sort(p+1,p+n+1,cmp);
for (int i=1;i<=n;++i)
num[p[i]]=i;

sz=0; root[0]=0;
for (int i=1;i<=n;++i){
root[i]=root[i-1];
build(root[i],1,n,num[i]);
}
for (int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&z);
ans=query(root[x-1],root[y],1,n,z);
printf("%d\n",val[p[ans]]);
}
}

动态主席树

// BZOJ 1901 Dynamic Rankings
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int max_n=1e4+5;
const int max_m=1e4+5;
const int max_log=30;
const int max_tree=3e6+5;

char opt[10];
int n,m,a,b,t,sz,N,cnt;
int val[max_n],A[max_m],B[max_m],K[max_m],flag[max_m];
int num[max_n*2],hash[max_n*2],root[max_n*2],L[max_log],R[max_log];
int sum[max_tree],ls[max_tree],rs[max_tree];

inline int find(int x){
int l=1,r=N,mid;
while (l<=r){
mid=(l+r)>>1;
if (hash[mid]<x) l=mid+1;
else r=mid-1;
}
return l;
}
inline void build(int last,int l,int r,int &now,int x,int v){
int mid=(l+r)>>1;
now=++sz;
sum[now]=sum[last]+v; ls[now]=ls[last]; rs[now]=rs[last];
if (l==r) return;
if (x<=mid) build(ls[last],l,mid,ls[now],x,v);
else build(rs[last],mid+1,r,rs[now],x,v);
}
inline int query(int l,int r,int k){
int mid=(l+r)>>1;
if (l==r) return l;
int suml=0,sumr=0;
for (int i=1;i<=a;++i) suml+=sum[ls[L[i]]];
for (int i=1;i<=b;++i) sumr+=sum[ls[R[i]]];
if (sumr-suml>=k){
for (int i=1;i<=a;++i) L[i]=ls[L[i]];
for (int i=1;i<=b;++i) R[i]=ls[R[i]];
return query(l,mid,k);
}
else{
for (int i=1;i<=a;++i) L[i]=rs[L[i]];
for (int i=1;i<=b;++i) R[i]=rs[R[i]];
return query(mid+1,r,k-(sumr-suml));
}
}

int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d",&val[i]),num[++cnt]=val[i];
for (int i=1;i<=m;++i){
scanf("%s",opt);
if (opt[0]=='C'){
scanf("%d%d",&A[i],&B[i]);
num[++cnt]=B[i];
}
else{
flag[i]=1;
scanf("%d%d%d",&A[i],&B[i],&K[i]);
}
}
sort(num+1,num+cnt+1);
hash[++N]=num[1];
for (int i=2;i<=cnt;++i)
if (num[i]!=num[i-1]) hash[++N]=num[i];

for (int i=1;i<=n;++i){
t=find(val[i]);
for (int j=i;j<=n;j+=j&(-j))
build(root[j],1,N,root[j],t,1);
}
for (int i=1;i<=m;++i)
if (flag[i]){
a=0,b=0,A[i]--;
for (int j=A[i];j>=1;j-=j&(-j)) L[++a]=root[j];
for (int j=B[i];j>=1;j-=j&(-j)) R[++b]=root[j];
printf("%d\n",hash[query(1,N,K[i])]);
}
else{
t=find(val[A[i]]);
for (int j=A[i];j<=n;j+=j&(-j)) build(root[j],1,N,root[j],t,-1);
val[A[i]]=B[i];
t=find(val[A[i]]);
for (int j=A[i];j<=n;j+=j&(-j)) build(root[j],1,N,root[j],t,1);
}
}

算法

高精度

加

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 505

char s1[N],s2[N];
int a[N],b[N];

void jia(int *a,int *b)
{
a[0]=max(a[0],b[0]);
for (int i=1;i<=a[0];++i) a[i]+=b[i];
for (int i=1;i<=a[0];++i)
{
a[i+1]+=a[i]/10;
a[i]%=10;
}
if (a[a[0]+1]) a[0]++;
}
int main()
{
scanf("%s",s1);scanf("%s",s2);
a[0]=strlen(s1);b[0]=strlen(s2);
for (int i=0;i<a[0];++i) a[i+1]=s1[a[0]-i-1]-'0';
for (int i=0;i<b[0];++i) b[i+1]=s2[b[0]-i-1]-'0';
jia(a,b);
for (int i=a[0];i>=1;--i) printf("%d",a[i]);
putchar('\n');
}

减

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 505

char s1[N],s2[N];
int a[N],b[N];
bool flag;

bool compare(int *a,int *b)
{
if (a[0]<b[0]) return 1;
else if (a[0]>b[0]) return 0;
for (int i=a[0];i>=1;--i)
{
if (a[i]<b[i]) return 1;
else if (b[i]<a[i]) return 0;
}
return 0;
}
void jian(int *a,int *b)
{
for (int i=1;i<=a[0];++i)
{
if (a[i]<b[i]) --a[i+1],a[i]+=10;
a[i]-=b[i];
}
while (a[0]>1&&!a[a[0]]) --a[0];
}
int main()
{
scanf("%s",s1);scanf("%s",s2);
a[0]=strlen(s1);b[0]=strlen(s2);
for (int i=0;i<a[0];++i) a[i+1]=s1[a[0]-i-1]-'0';
for (int i=0;i<b[0];++i) b[i+1]=s2[b[0]-i-1]-'0';
flag=compare(a,b);
if (flag)
for (int i=0;i<=max(a[0],b[0]);++i) swap(a[i],b[i]);
jian(a,b);
if (flag) putchar('-');
for (int i=a[0];i>=1;--i) printf("%d",a[i]);
putchar('\n');
}

乘

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 1005

char s1[N],s2[N];
int a[N],b[N],ans[N];

void cheng(int *a,int *b)
{
ans[0]=a[0]+b[0]-1;
for (int i=1;i<=a[0];++i)
for (int j=1;j<=b[0];++j)
ans[i+j-1]+=a[i]*b[j];
for (int i=1;i<=ans[0];++i)
{
ans[i+1]+=ans[i]/10;
ans[i]%=10;
}
while (ans[ans[0]+1])
{
ans[0]++;
ans[ans[0]+1]=ans[ans[0]]/10;
ans[ans[0]]%=10;
}
}
int main()
{
scanf("%s",s1);scanf("%s",s2);
a[0]=strlen(s1);b[0]=strlen(s2);
for (int i=0;i<a[0];++i) a[i+1]=s1[a[0]-i-1]-'0';
for (int i=0;i<b[0];++i) b[i+1]=s2[b[0]-i-1]-'0';
cheng(a,b);
for (int i=ans[0];i>=1;--i) printf("%d",ans[i]);
putchar('\n');
}

除

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 1005

char s1[N],s2[N];
int a[N],b[N],c[N],tmp[N];

void copy(int *a,int *b,int loc)
{
for (int i=1;i<=a[0];++i) b[i+loc-1]=a[i];
b[0]=a[0]+loc-1;
}
int compare(int *a,int *b)
{
if (a[0]>b[0]) return 1;
if (a[0]<b[0]) return -1;
for (int i=a[0];i>=1;--i)
{
if (a[i]>b[i]) return 1;
else if (a[i]<b[i]) return -1;
}
return 0;
}
void jian(int *a,int *b)
{
int flag=compare(a,b);
if (flag==0)
{
a[0]=1,a[1]=0;
return;
}
if (flag==1)
{
for (int i=1;i<=a[0];++i)
{
if (a[i]<b[i]) --a[i+1],a[i]+=10;
a[i]-=b[i];
}
while (a[0]>1&&!a[a[0]]) --a[0];
}
}
void chu(int *a,int *b,int *c)
{
c[0]=a[0]-b[0]+1;
for (int i=c[0];i>=1;--i)
{
memset(tmp,0,sizeof(tmp));
copy(b,tmp,i);
while (compare(a,tmp)>=0) c[i]++,jian(a,tmp);
}
while (c[0]>1&&!c[c[0]]) --c[0];
}

int main()
{
scanf("%s",s1);scanf("%s",s2);
a[0]=strlen(s1);b[0]=strlen(s2);
for (int i=0;i<a[0];++i) a[i+1]=s1[a[0]-i-1]-'0';
for (int i=0;i<b[0];++i) b[i+1]=s2[b[0]-i-1]-'0';
chu(a,b,c);
for (int i=c[0];i>=1;--i) putchar(c[i]+'0');putchar('\n');
}

归并排序求逆序对

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long
#define N 100005

int n,k;LL rev;
int a[N],s[N],b[N];

void mergesort(int l,int r)
{
int mid=(l+r)>>1;
if (l==r) return;
mergesort(l,mid);
mergesort(mid+1,r);
int i=l,j=mid+1,now=l;
while (i<=mid&&j<=r)
{
if (s[i]<s[j]) b[now++]=s[i++];
else b[now++]=s[j++],rev+=(LL)mid-i+1;
}
while (i<=mid) b[now++]=s[i++];
while (j<=r) b[now++]=s[j++];
for (;l<=r;++l) s[l]=b[l];
}
int main()
{
scanf("%d%d",&n,&k);
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
for (int i=1;i<=n;++i)
{
s[i]=s[i-1]+a[i]-k;
if (s[i]<=0) ++rev;
}
mergesort(1,n);
printf("%lld\n",(LL)(n+1)*n/2-rev);
}

网络流

Dinic

// codevs 1993
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
#define N 10005
#define inf 1000000000

int n,m,maxflow,x,y,z;
int tot,point[N],nxt[N],v[N],remain[N];
int cur[N],deep[N],last[N],num[N];
queue <int> q;

{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
bool bfs(int s,int t)
{
for (int i=1;i<=t;++i) deep[i]=t;
deep[s]=0;
for (int i=1;i<=t;++i) cur[i]=point[i];
q.push(s);
while (!q.empty())
{
int now=q.front();q.pop();
for (int i=point[now];i!=-1;i=nxt[i])
if (deep[v[i]]==t&&remain[i])
{
deep[v[i]]=deep[now]+1;
q.push(v[i]);
}
}
return deep[t]<t;
}
int dfs(int now,int t,int limit)
{
if (now==t||!limit) return limit;
int flow=0,f;
for (int i=cur[now];i!=-1;i=nxt[i])
{
cur[now]=i;
if (deep[v[i]]==deep[now]+1&&(f=dfs(v[i],t,min(remain[i],limit))))
{
flow+=f;
limit-=f;
remain[i]-=f;
remain[i^1]+=f;
if (!limit) break;
}
}
return flow;
}
void dinic(int s,int t)
{
while (bfs(s,t))
maxflow+=dfs(s,t,inf);
}
int main()
{
tot=-1;
memset(point,-1,sizeof(point));
memset(nxt,-1,sizeof(nxt));
scanf("%d%d",&m,&n);
for (int i=1;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&z);
}
dinic(1,n);
printf("%d\n",maxflow);
}

Isap

// codevs 1993
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
#define N 10005
#define inf 1000000000

int n,m,maxflow,x,y,z;
int tot,point[N],nxt[N],v[N],remain[N];
int cur[N],deep[N],last[N],num[N];
queue <int> q;

{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
void bfs(int t)
{
for (int i=1;i<=t;++i) deep[i]=t;
deep[t]=0;
for (int i=1;i<=t;++i) cur[i]=point[i];
q.push(t);
while (!q.empty())
{
int now=q.front();q.pop();
for (int i=point[now];i!=-1;i=nxt[i])
if (deep[v[i]]==t&&remain[i^1])
{
deep[v[i]]=deep[now]+1;
q.push(v[i]);
}
}
}
{
int now=t,ans=inf;
while (now!=s)
{
ans=min(ans,remain[last[now]]);
now=v[last[now]^1];
}
now=t;
while (now!=s)
{
remain[last[now]]-=ans;
remain[last[now]^1]+=ans;
now=v[last[now]^1];
}
return ans;
}
void isap(int s,int t)
{
bfs(t);
for (int i=1;i<=t;++i) ++num[deep[i]];

int now=s;
while (deep[s]<t)
{
if (now==t)
{
now=s;
}
bool has_find=0;
for (int i=cur[now];i!=-1;i=nxt[i])
{
cur[now]=i;
if (deep[now]==deep[v[i]]+1&&remain[i])
{
has_find=1;
last[v[i]]=i;
now=v[i];
break;
}
}
if (!has_find)
{
int minn=t-1;
for (int i=point[now];i!=-1;i=nxt[i])
if (remain[i]) minn=min(minn,deep[v[i]]);
if (!(--num[deep[now]])) break;
++num[deep[now]=minn+1];
cur[now]=point[now];
if (now!=s) now=v[last[now]^1];
}
}
}
int main()
{
tot=-1;
memset(point,-1,sizeof(point));
memset(nxt,-1,sizeof(nxt));
scanf("%d%d",&m,&n);
for (int i=1;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&z);
}
isap(1,n);
printf("%d\n",maxflow);
}

最小费用最大流

// codevs1237 餐巾计划问题
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;

const int max_N=1005;
const int max_Max=max_N*2+2;
const int max_m=max_Max*20;
const int max_e=max_m*2;
const int inf=1e9;

int N,p,m,f,n,s,Max,maxflow,mincost,r[max_N];
int point[max_Max],next[max_e],v[max_e],remain[max_e],c[max_e],tot;
int last[max_Max],dis[max_Max];
bool vis[max_Max];
queue <int> q;

inline void addedge(int x,int y,int cap,int z){
++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap; c[tot]=z;
++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0; c[tot]=-z;
}

int ans=inf,now=t;
while (now!=s){
ans=min(ans,remain[last[now]]);
now=v[last[now]^1];
}

now=t;
while (now!=s){
remain[last[now]]-=ans;
remain[last[now]^1]+=ans;
now=v[last[now]^1];
}

return ans;
}

inline bool bfs(int s,int t){
memset(dis,0x7f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[s]=0;
vis[s]=true;
while (!q.empty()) q.pop();
q.push(s);

while (!q.empty()){
int now=q.front(); q.pop();
vis[now]=false;
for (int i=point[now];i!=-1;i=next[i])
if (dis[v[i]]>dis[now]+c[i]&&remain[i]){
dis[v[i]]=dis[now]+c[i];
last[v[i]]=i;
if (!vis[v[i]]){
vis[v[i]]=true;
q.push(v[i]);
}
}
}

if (dis[t]>inf) return false;
maxflow+=flow;
mincost+=flow*dis[t];
return true;
}

inline void major(int s,int t){
maxflow=0; mincost=0;
while (bfs(s,t));
}

int main(){
tot=-1;
memset(point,-1,sizeof(point));
memset(next,-1,sizeof(next));

scanf("%d%d%d%d%d%d",&N,&p,&m,&f,&n,&s);
for (int i=1;i<=N;++i)
scanf("%d",&r[i]);
Max=N*2+2;
for (int i=1;i<=N;++i)
for (int i=1;i<=N;++i)
for (int i=1;i<=N;++i)
for (int i=1;i<N;++i)
for (int i=1;i<=N;++i){
if (i+m<=N)
if (i+n<=N)
}

major(1,Max);
printf("%d\n",mincost);
}

二分图判断、最大匹配数

// hdu 2444
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 40005

int n,m,x,y,ans;
bool flag;
int tot,point[N],nxt[N*2],v[N*2];
int belong[N],vis[N],col[N];

void clear()
{
ans=0;
tot=0;memset(point,0,sizeof(point));memset(v,0,sizeof(v));memset(nxt,0,sizeof(nxt));
memset(belong,0,sizeof(belong));memset(vis,0,sizeof(vis));memset(col,-1,sizeof(col));
}
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void dfs(int x,int fa)
{
for (int i=point[x];i&&flag;i=nxt[i])
if (v[i]!=fa)
{
if (col[v[i]]==-1)
{
col[v[i]]=col[x]^1;
dfs(v[i],x);
}
else
{
if (col[v[i]]!=(col[x]^1)) flag=false;
return;
}
}
}
bool find(int x,int k)
{
for (int i=point[x];i;i=nxt[i])
if (vis[v[i]]!=k)
{
vis[v[i]]=k;
if (!belong[v[i]]||find(belong[v[i]],k))
{
belong[v[i]]=x;
return true;
}
}
return false;
}
int main()
{
while (~scanf("%d%d",&n,&m))
{
clear();
if (n==1)
{
puts("No");
continue;
}
for (int i=1;i<=m;++i)
{
scanf("%d%d",&x,&y);
}
flag=true;
col[1]=0;dfs(1,0);
if (!flag)
{
puts("No");
continue;
}
for (int i=1;i<=n;++i)
if (find(i,i)) ans++;
printf("%d\n",ans>>1);
}
}

Dijkstra 堆优化

// poj 2387
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
#define INF 2147483647
#define N 2005

int n,m,x,y,z,dis[N];
int tot,nxt[N*2],point[N],v[N*2],c[N*2];
bool vis[N*2];
struct hp
{
int x,val;
bool operator < (const hp &a) const
{
return a.val<val;
}
};
priority_queue <hp> q;

inline void addedge(int x,int y,int z)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=z;
}
inline void dijkstra()
{
memset(dis,127,sizeof(dis));dis[1]=0;
q.push((hp){1,0});
while (!q.empty())
{
int now=q.top().x;q.pop();
if (vis[now]) continue; vis[now]=true;
for (int i=point[now];i;i=nxt[i])
if (!vis[v[i]]&&dis[now]+c[i]<dis[v[i]])
{
dis[v[i]]=dis[now]+c[i];
q.push((hp){v[i],dis[v[i]]});
}
}
}
int main()
{
scanf("%d%d",&m,&n);
for (int i=1;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&z);
}
dijkstra();
printf("%d\n",dis[n]);
}

字符串

Kmp

// poj 3461
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_W=10005;
const int max_s=1000005;
char W[max_W],s[max_s];
int T[max_W];
int t,len_W,len_s,ans;

inline void calc_T()
{
T[0]=-1;
int j;
for (int i=0;i<len_W;++i)
{
j=T[i];
while (j!=-1&&W[j]!=W[i])
j=T[j];
T[i+1]=++j;
}
}
inline void calc_ans()
{
int j=0;
for (int i=0;i<len_s;++i)
{
while (j!=-1&&W[j]!=s[i])
j=T[j];
j++;
if (j==len_W)
{
ans++;
j=T[j];
}
}
}
int main(){
scanf("%d\n",&t);
while (t--){
gets(W);
gets(s);
len_W=strlen(W);
len_s=strlen(s);
memset(T,0,sizeof(T));
calc_T();
ans=0;
calc_ans();
printf("%d\n",ans);
}
}

AC自动机

// hdu 2222
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define N 500005

char s[N*2];
int T,n,sz,ans;
int ch[N][30],is_end[N],fail[N];
bool vis[N];
queue <int> q;

void clear()
{
n=sz=ans=0;
memset(ch,0,sizeof(ch));memset(is_end,0,sizeof(is_end));
memset(fail,0,sizeof(fail));memset(vis,0,sizeof(vis));
}
void insert()
{
int len=strlen(s),now=0;
for (int i=0;i<len;++i)
{
int x=s[i]-'a';
if (!ch[now][x]) ch[now][x]=++sz;
now=ch[now][x];
}
++is_end[now];
}
void make_fail()
{
while (!q.empty()) q.pop();
for (int i=0;i<26;++i)
if (ch[0][i]) q.push(ch[0][i]);
while (!q.empty())
{
int now=q.front();q.pop();
for (int i=0;i<26;++i)
{
if (!ch[now][i])
{
ch[now][i]=ch[fail[now]][i];
continue;
}
fail[ch[now][i]]=ch[fail[now]][i];
q.push(ch[now][i]);
}
}
}
void ac()
{
int len=strlen(s),now=0;
for (int i=0;i<len;++i)
{
vis[now]=1;
int x=s[i]-'a';
int y=ch[now][x];
while (y&&!vis[y])
{
vis[y]=1;
ans+=is_end[y];
y=fail[y];
}
now=ch[now][x];
}
}
int main()
{
scanf("%d",&T);
while (T--)
{
clear();
scanf("%d\n",&n);
for (int i=1;i<=n;++i)
{
gets(s);
insert();
}
gets(s);
make_fail();
ac();
printf("%d\n",ans);
}
}

后缀数组

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int max_n=2e5+5;

int n,m=300,sa[max_n],c[max_n],x[max_n],y[max_n],rank[max_n],height[max_n];
char s[max_n];

inline void build_sa(){
for (int i=0;i<m;++i) c[i]=0;
for (int i=0;i<n;++i) c[x[i]=s[i]]++;
for (int i=1;i<m;++i) c[i]+=c[i-1];
for (int i=n-1;i>=0;--i) sa[--c[x[i]]]=i;

for (int k=1;k<=n;k<<=1){
int p=0;
for (int i=n-k;i<n;++i) y[p++]=i;
for (int i=0;i<n;++i) if (sa[i]>=k) y[p++]=sa[i]-k;

for (int i=0;i<m;++i) c[i]=0;
for (int i=0;i<n;++i) c[x[y[i]]]++;
for (int i=1;i<m;++i) c[i]+=c[i-1];
for (int i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];

swap(x,y);
p=1; x[sa[0]]=0;
for (int i=1;i<n;++i) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&
((sa[i-1]+k>=n?-1:y[sa[i-1]+k])==(sa[i]+k>=n?-1:y[sa[i]+k]))?p-1:p++;
if (p>n) break;
m=p;
}
}

inline void build_lcp(){
for (int i=0;i<n;++i) rank[sa[i]]=i;
height[0]=0;
int k=0;
for (int i=0;i<n;++i){
if (!rank[i]) continue;
if (k) --k;
int j=sa[rank[i]-1];
while (i+k<n&&j+k<n&&s[i+k]==s[j+k]) ++k;
height[rank[i]]=k;
}
}

int main(){
gets(s);
n=strlen(s);
build_sa();
build_lcp();
for (int i=0;i<n;++i) printf("%d%c",sa[i]+1," \n"[i==n-1]);
for (int i=0;i<n;++i) printf("%d%c",height[i]," \n"[i==n-1]);
}

Tarjan

Tarjan（强连通分量）/spfa

// BZOJ 1179
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define N 500005

int n,m,s,p,dfs_clock,scc,ans;
struct hp{int x,y;}e[N];
int val[N],bar[N],dfn[N],low[N],stack[N],tmp,belong[N],size[N],dis[N];
int tot,point[N],nxt[N],v[N];
bool vis[N];
queue <int> q;

{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
}
void tarjan(int x)
{
dfn[x]=low[x]=++dfs_clock;vis[x]=true;stack[++tmp]=x;
for (int i=point[x];i;i=nxt[i])
if (!dfn[v[i]])
{
tarjan(v[i]);
low[x]=min(low[x],low[v[i]]);
}
else if (vis[v[i]])
low[x]=min(low[x],dfn[v[i]]);
if (dfn[x]==low[x])
{
++scc;int now=0;
while (now!=x)
{
now=stack[tmp--];
vis[now]=false;
belong[now]=scc;
size[scc]+=val[now];
}
}
}
void rebuild()
{
tot=0;memset(point,0,sizeof(point));
for (int i=1;i<=m;++i)
if (belong[e[i].x]!=belong[e[i].y])
}
void spfa()
{
memset(vis,0,sizeof(vis));
dis[belong[s]]=size[belong[s]];vis[belong[s]]=true;q.push(belong[s]);
while (!q.empty())
{
int now=q.front();q.pop();
vis[now]=false;
for (int i=point[now];i;i=nxt[i])
if (dis[v[i]]<dis[now]+size[v[i]])
{
dis[v[i]]=dis[now]+size[v[i]];
if (!vis[v[i]])
{
vis[v[i]]=true;
q.push(v[i]);
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
scanf("%d%d",&e[i].x,&e[i].y);
}
for (int i=1;i<=n;++i) scanf("%d",&val[i]);
scanf("%d%d",&s,&p);
for (int i=1;i<=p;++i) scanf("%d",&bar[i]);

for (int i=1;i<=n;++i)
if (!dfn[i]) tarjan(i);
rebuild();
spfa();
for (int i=1;i<=p;++i)
ans=max(ans,dis[belong[bar[i]]]);
printf("%d\n",ans);
}

Tarjan（双连通分量）

// POJ 3177
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 10005

int n,m,dfs_clock,dcc,ans;
int tot,point[N],nxt[N*2],v[N*2];
int dfn[N],low[N],stack[N],tmp,belong[N],du[N];
struct hp{int x,y;}e[N];
bool vis[N];

{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void tarjan(int x,int fa)
{
dfn[x]=low[x]=++dfs_clock;vis[x]=true;stack[++tmp]=x;
bool flag=false;
for (int i=point[x];i;i=nxt[i])
{
if (v[i]==fa&&!flag)
{
flag=true;
continue;
}
if (!dfn[v[i]])
{
tarjan(v[i],x);
low[x]=min(low[x],low[v[i]]);
}
else if (vis[v[i]]) low[x]=min(low[x],dfn[v[i]]);
}
if (dfn[x]==low[x])
{
dcc++;int now=0;
while (now!=x)
{
now=stack[tmp--];
belong[now]=dcc;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
scanf("%d%d",&e[i].x,&e[i].y);
}
for (int i=1;i<=n;++i)
if (!dfn[i]) tarjan(i,0);
for (int i=1;i<=m;++i)
if (belong[e[i].x]!=belong[e[i].y])
du[belong[e[i].x]]++,du[belong[e[i].y]]++;
for (int i=1;i<=dcc;++i)
if (du[i]==1) ans++;
ans=(ans+1)>>1;
printf("%d\n",ans);
}

Tarjan（求割点及去掉割点之后连通块数量）

// POJ 1523
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 500005

int n,m,x,y,dfs_clock,Case;
int tot,point[1005],nxt[N*2],v[N*2];
int dfn[1005],low[1005],ans[1005];
bool flag;

void clear()
{
n=m=x=y=dfs_clock=tot=flag=0;
memset(v,0,sizeof(v));memset(point,0,sizeof(point));memset(nxt,0,sizeof(nxt));
memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(ans,0,sizeof(ans));
}
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void tarjan(int x)
{
dfn[x]=low[x]=++dfs_clock;
for (int i=point[x];i;i=nxt[i])
if (!dfn[v[i]])
{
tarjan(v[i]);
low[x]=min(low[x],low[v[i]]);
if (dfn[x]<=low[v[i]]) ans[x]++;
}
else low[x]=min(low[x],dfn[v[i]]);
}
int main()
{
while (1)
{
clear();
m=0;
while (1)
{
scanf("%d",&x);if (!x) break;
n=max(n,x);n=max(n,y);
}
if (!m) break;

tarjan(1);
printf("Network #%d\n",++Case);
flag=false;
for (int i=1;i<=n;++i)
if (i==1&&ans[i]>1)
{
flag=true;
printf("  SPF node %d leaves %d subnets\n",i,ans[i]);
}
else if (i!=1&&ans[i]+1>1)
{
flag=true;
printf("  SPF node %d leaves %d subnets\n",i,ans[i]+1);
}

if (!flag) puts("  No SPF nodes");
putchar('\n');
}
}

悬线法

// BZOJ 3039
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 1005

int n,m,a[N][N],L[N][N],R[N][N],l[N][N],r[N][N],h[N][N],ans;

int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
{
char ch=getchar();
while (ch!='R'&&ch!='F') ch=getchar();
if (ch=='R') a[i][j]=1;
}
for (int i=1;i<=n;++i)
{
int Max=0,Min=m+1;
for (int j=1;j<=m;++j)
{
if (a[i][j]) Max=max(Max,j);
L[i][j]=Max;
}
for (int j=m;j>=1;--j)
{
if (a[i][j]) Min=min(Min,j);
R[i][j]=Min;
}
}
for (int j=1;j<=m;++j) r[0][j]=m+1;
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
{
if (a[i][j])
{
h[i][j]=0;
l[i][j]=0,r[i][j]=m+1;
}
else
{
h[i][j]=h[i-1][j]+1;
l[i][j]=max(l[i-1][j],L[i][j]);
r[i][j]=min(r[i-1][j],R[i][j]);
}
}
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
ans=max(ans,(r[i][j]-l[i][j]-1)*h[i][j]);
printf("%d\n",3*ans);
}

数学相关

快速幂

int fast_pow(int a,int p)
{
int ans=1;
for (;p;p>>=1,a=(a*a)%Mod)
if (p&1)
ans=(ans*a)%Mod;
return ans;
}

欧几里得算法

int gcd(int a,int b)
{
if (!b) return a;
else return gcd(b,a%b);
}

扩展欧几里得算法

// BZOJ 1477
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long

LL x,y,m,n,L,a,b,c;

inline LL gcd(LL a,LL b){
if (!b) return a;
else return gcd(b,a%b);
}

inline void exgcd(LL a,LL b,LL &x,LL &y){
if (!b) x=1,y=0;
else exgcd(b,a%b,y,x),y-=a/b*x;
}

int main(){
scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&L);
a=n-m; b=L; c=x-y;
int t=gcd(a,b);
if (c%t){
printf("Impossible\n");
return 0;
}
a/=t; b/=t; c/=t;
x=y=0;
exgcd(a,b,x,y);
x=((c*x)%b+b)%b;
if (!x) x+=b;
printf("%lld\n",x);
}

欧拉筛（phi/mu/d/t/g/f）

inline void get(){
phi[1]=1; mu[1]=1; d[1]=1; t[1]=1; f[1]=1;
for (LL i=2;i<=N;++i)
{
if (!p[i])
{
phi[i]=i-1; mu[i]=-1; d[i]=2; t[i]=1; f[i]=(i*i+1)%m; g[i]=1;
prime[++prime[0]]=i;
}
for (LL j=1;j<=prime[0]&&i*prime[j]<=N;++j)
{
p[i*prime[j]]=1;
if (i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
mu[i*prime[j]]=0;
t[i*prime[j]]=t[i]+1;
d[i*prime[j]]=d[i]/(t[i]+1)*(t[i*prime[j]]+1);
g[i*prime[j]]=g[i];
f[i*prime[j]]=f[i]*prime[j]*prime[j]+f[g[i]];
break;
}
else
{
phi[i*prime[j]]=phi[i]*(prime[j]-1);
mu[i*prime[j]]=-mu[i];
d[i*prime[j]]=d[i]*2;
t[i*prime[j]]=1;
g[i*prime[j]]=i;
f[i*prime[j]]=f[i]*prime[j]*prime[j]+f[i];
}
}
}
}

根n求phi

inline LL phi(LL x){
LL ans=x;
for (LL i=2;i*i<=x;++i)
if (x%i==0){
ans=ans*(i-1)/i;
while (x%i==0) x/=i;
}
if (x>1) ans=ans*(x-1)/x;
return ans;
}