CSP前算法模板复习
强联通分量模板
void tarjan(int x){
dfn[x]=low[x]=++Time;
stk[++top]=x;
for(int i=head[x];~i;i=e[i].nxt){
int v=e[i].v;
if(!dfn[v]){
tarjan(v);
chkmin(low[x],low[v]);
}
else if(!color[v])chkmin(low[x],dfn[v]);
}
if(low[x]==dfn[x]){
++color_cnt;
do color[stk[top]]=color_cnt;while(top&&stk[top--]!=x);
}
}
割点模板
void tarjan(int x,int rt){
int cnt=0;
dfn[x]=low[x]=++Time;
for(int i=head[x];~i;i=e[i].nxt){
int v=e[i].v;
if(!dfn[v]){
fa[v]=x;
tarjan(v,rt);
chkmin(low[x],low[v]);
if(low[v]>=dfn[x]&&u!=rt)cut[x]=1;
if(x==rt)++cnt;
}
else if(fa[x]!=v) chkmin(low[x],dfn[v]);
}
if(x==rt&&cnt>=2)cut[x]=1;
}
割边模板
void tarjan(int x,int fa){
dfn[x]=low[x]=++Time;
for(int i=head[x];~i;i=e[i].nxt){
int v=e[i].v;
if(!dfn[v]){
tarjan(v,x);
chkmin(low[x],low[v]);
if(low[v]>dfn[x])cut[i]=1;
}
else if(v!=fa)chkmin(low[x],dfn[v]);
}
}
最小生成树:Kruskal算法
inline void Kruskal(){
sort(e+1,e+m+1);
int cnt=0,ans=0;
for(int i=1;i<=m;++i)
{
int u=find(e[i].u),v=find(e[i].v),w=e[i].w;
if(u!=v)
{
fa[u]=v;
ans+=w;
++cnt;
}
if(cnt==n-1)break;
}
}
堆优化Prim算法
typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> >pq;
inline void Prim()
{
int cnt=0,ans=0;
memset(dis,127,sizeof dis);
while(!pq.empty())
{
pii now=pq.top();pq.pop();
if(vis[now.second])continue;
vis[now.second]=1;
ans+=now.first;
for(int i=head[now.first];~i;i=e[i].nxt){
int v=e[i].v;
if(e[i].w<dis[v])
dis[v]=e[i].w,pq.push(pii(dis[v],v));
}
++cnt;
if(cnt==n-1)break;
}
}
01背包
const int N=1e3+7;
int f[N],w[N],c[N];
int main(void)
{
int n=gi,V=gi;
for(int i=1;i<=n;++i)c[i]=gi,w[i]=gi;
for(int i=1;i<=n;++i)
for(int j=V;j>=a[i];--j)
chkmax(f[j],f[j-c[i]]+w[i]);
return 0;
}
完全背包
const int N=1e3+7;
int f[N],w[N],c[N];
int main(void)
{
int n=gi,V=gi;
for(int i=1;i<=n;++i)c[i]=gi,w[i]=gi;
for(int i=1;i<=n;++i)
for(int j=a[i];j<=V;++j)
chkmax(f[j],f[j-c[i]]+w[i]);
return 0;
}
多重背包
略,(单调队列我也不会啊)
树状数组
struct BIT{
int c[N];
inline void add(int x,int y){
for(;x<=n;x+=x&-x)c[x]+=y;
}
inline int query(int x){
int ret=0;
for(;x;x-=x&-x)ret+=c[x];
return ret;
}
};
线段树
const int N=1e5+7;
struct SegmentTree{
int sum[N<<2],tag[N<<2];
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
inline void pushtag(int rt,int l,int r,int v){
tag[rt]+=v,sum[rt]+=(r-l+1)*v;
}
inline void pushdown(int rt,int l,int r)
{
if(tag[rt]){
pushtag(ls,l,mid,tag[rt]);
pushtag(rs,mid+1,r,tag[rt]);
tag[rt]=0;
}
}
inline void pushup(int rt){
sum[rt]=sum[ls]+sum[rs];
}
inline void modify(int rt,int l,int r,int L,int R,int v){
if(L<=l&&r<=R){
pushtag(rt,l,r,v);
return;
}
pushdown(rt,l,r);
if(L<=mid)modify(ls,l,mid,L,R,v);
if(R>mid)modify(rs,mid+1,r,L,R,v);
pushup(rt);
}
inline int query(int rt,int l,int r,int L,int R){
if(L<=l&&r<=R)return sum[rt];
pushdown(rt,l,r);
int ret=0;
if(L<=mid)ret+=query(ls,l,mid,L,R);
if(R>mid)ret+=query(rs,mid+1,r,L,R);
return ret;
}
};
Miller_Rabin
bool Test(ll a,ll x)
{
if(a>=x)return 1;
ll ret=qpow(a,x-1,x),s=x^1;
while(ret==1&&!(s&1))s>>=1,ret=qpow(a,s,x);
return ret==1||ret==(x^1);
}
/*
可以从后往前检测,似乎会更快
bool Test(ll a,ll x)
{
if(a>=x)return 1;
ll ret,s=x^1;
int p=__builtin_ctzll(s);
ret=qpow(a,s>>p,x);
if(ret==1||ret==(x^1))return 1;
while(p--&&ret!=(x^1))ret=mul(ret,ret,x);
return p>=0;
}
*/
线性筛
int npr[N],pr[N],cnt;
void sieve(int n)
{
npr[1]=1;
for(int i=2;i<=n;++i){
if(!npr[i]){
pr[++cnt]=i;
}
for(int j=1;j<=cnt&&pr[j]*i<=n;++j)
{
npr[pr[j]*i]=1;
if(i%pr[j]==0)break;
}
}
}
普通平衡树
const int N=1e5+7;
int top,cnt;
struct SplayTree{
struct node;
typedef node* tree;
struct node{
int val,siz,cnt;
tree par,ch[2];
node(){}
node(int v,tree fa):val(v),siz(1),cnt(1),par(fa){ch[0]=ch[1]=NULL;}
}*root;
static node pool[N<<2],*stk[N<<2];
inline tree newnode(int val,tree par){return &(*(top?stk[top--]:pool+(++cnt))=node(val,par));}
inline void delnode(tree &x){stk[++top]=x,x=NULL;}
inline int siz(tree x){return x?x->siz:0;}
inline bool ws(tree x,tree p){return p?p->ch[1]==x:0;}
inline void pushup(tree x){if(x)x->siz=siz(x->ch[0])+siz(x->ch[1])+x->cnt;}
inline void connect(tree x,tree p,bool wson){x?x->par=p:0,(p?p->ch[wson]:root)=x;}
inline void rotate(tree x){
tree p=x->par,g=p->par;
bool t=ws(x,p);
connect(x,g,ws(p,g));
connect(x->ch[!t],p,t);
connect(p,x,!t);
pushup(p);
}
inline tree adjust(tree x,bool p,bool q)
{
tree k=x->ch[p];
while(k&&k->ch[q])k=k->ch[q];
return Splay(k,x),x;
}
inline tree Splay(tree x,tree y=NULL){
while(x&&x->par!=y){
tree p=x->par,g=p->par;
if(g!=y)rotate(ws(x,p)^ws(p,g)?x:p);
rotate(x);
}
return pushup(x),x;
}
inline tree find(int val){
tree x=root;
while(x&&x->val!=val&&x->ch[val>x->val])x=x->ch[val>x->val];
return Splay(x),x;
}
inline tree findkth(int k){
tree x=root;
while(x)
if(siz(x->ch[0])+x->cnt>=k&&siz(x->ch[0])<k)return x;
else if(siz(x->ch[0])>=k)x=x->ch[0];
else k-=siz(x->ch[0])+x->cnt,x=x->ch[1];
assert(0);
}
inline void erase(int val){
tree x=find(val);
if(x->cnt>1)return --x->cnt,void();
adjust(x,0,1);
connect(x->ch[0],NULL,0),connect(x->ch[1],root,1);
delnode(x);
}
inline tree insert(int val){
if(!root)return root=newnode(val,NULL);
for(tree x=root;x;x=x->ch[val>x->val])
{
if(x->val==val)return ++x->cnt,Splay(x);
if(!x->ch[val>x->val])return Splay(x->ch[val>x->val]=newnode(val,x));
}
}
inline int rank(int x){return siz(find(x)->ch[0])+1;}
inline tree pre(int x){
tree tmp=adjust(insert(x),0,1)->ch[0];
return erase(x),tmp;
}
inline tree nxt(int x){
tree tmp=adjust(insert(x),1,0)->ch[1];
return erase(x),tmp;
}
}bt;
SplayTree::node SplayTree::pool[N<<2],*SplayTree::stk[N<<2];
单源最短路(堆优化\(dijkstra\))
typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> >Q;
int vis[N],dis[N];
inline void dijkstra(){
memset(dis,127,sizeof dis);
dis[S]=0;
Q.push(pii(0,S));
while(!Q.empty())
{
int now=Q.top().second;Q.pop();
if(vis[now])continue;
vis[now]=1;
for(int i=head[now];~i;i=e[i].nxt){
int v=e[i].v;
if(dis[v]>dis[now]+e[i].w){
dis[v]=dis[now]+e[i].w;
if(!vis[v])Q.push(pii(dis[v],v));
}
}
}
}
单源最短路\(SPFA\)
int dis[N],vis[N];
queue<int>Q;
inline void spfa()
{
memset(dis,127,sizeof dis);
dis[S]=0;
Q.push(S);
while(!Q.empty())
{
int now=Q.front();Q.pop();
vis[now]=0;
for(int i=head[now];~i;i=e[i].nxt){
int v=e[i].v;
if(dis[v]>dis[now]+e[i].w){
dis[v]=dis[now]+e[i].w;
if(!vis[now])Q.push(now),vis[now]=1;
}
}
}
}
\(ST\)表
#define lg2(x) (31-__builtin_clz(x))
int f[21][N],a[N];
inline void STinit(int n){
int len=lg2(n);
for(int i=1;i<=n;++i)f[0][i]=a[i];
for(int i=1;i<=len;++i)
for(int j=1;j+(1<<i)-1<=n;++j)
f[i][j]=min(f[i-1][j],f[i-1][j+(1<<i)-1]);
}
inline int Query(int l,int r){
if(l>r)swap(l,r);
int k=lg2(r-l+1);
return min(f[k][l],f[k][r-(1<<k)+1]);
}
文艺平衡树
struct SplayTree{
struct node;
typedef node* tree;
struct node{
int val,siz,rev;
tree par,ch[2];
node(){}
node(int v,tree fa):val(v),siz(1),rev(0),par(fa){ch[0]=ch[1]=NULL;}
}*root;
inline int siz(tree x){return x?x->siz:0;}
inline bool ws(tree x,tree p){return p?p->ch[1]==x:0;}
inline void connect(tree x,tree p,bool which){x?x->par=p:0,(p?p->ch[which]:root)=x;}
inline void pushup(tree x){if(x)x->siz=siz(x->ch[0])+siz(x->ch[1])+1;}
inline void pushtag(tree x){if(x)std::swap(x->ch[0],x->ch[1]),x->rev^=1;}
inline void pushdown(tree x){if(x&&x->rev)pushtag(x->ch[0]),pushtag(x->ch[1]),x->rev=0;}
inline int size(){return siz(root);}
inline void rotate(tree x)
{
tree p=x->par,g=p->par;
bool t=ws(x,p);
connect(x,g,ws(p,g));
connect(x->ch[!t],p,t);
connect(p,x,!t);
pushup(p);
}
inline tree Splay(tree x,tree y=NULL)
{
while(x&&x->par!=y){
tree p=x->par,g=p->par;
if(g!=y)rotate(ws(x,p)^ws(p,g)?x:p);
rotate(x);
}
return pushup(x),x;
}
inline tree adjust(tree x,bool p,bool q){
tree k=x->ch[p];
while(k&&k->ch[q])k=k->ch[q];
return Splay(k,x),x;
}
inline tree findkth(int k){
if(k<1||k>size())return NULL;
tree x=root;
while(x)
{
pushdown(x);
if(siz(x->ch[0])+1==k)return x;
else if(siz(x->ch[0])>=k)x=x->ch[0];
else k-=siz(x->ch[0])+1,x=x->ch[1];
}
}
inline tree split(int l,int r){
if(l>r)return NULL;
tree L=findkth(l-1),R=findkth(r+1);
Splay(L),Splay(R,L);
return l==1&&r==size()?root:(l==1?root->ch[0]:(r==size()?root->ch[1]:root->ch[1]->ch[0]));
}
inline void reverse(int l,int r){
tree x=split(l,r);
pushtag(x);
}
inline void merge(tree &a,tree &b){
if(!a)return std::swap(b,a),void();
if(!b)return;
if(a->ch[1])
{
adjust(a,1,1);
connect(b,a->ch[1],1);
pushup(a->ch[1]);
}
else connect(b,a,1);
pushup(a);
}
inline tree cut(tree x){
if(!x)return NULL;
tree p=x->par;
if(p)p->ch[ws(x,p)]=0;
x->par=0;
return pushup(p),p;
}
inline void swap(int l1,int r1,int l2,int r2){
int siz1=r1-l1+1,siz2=l2-r1-1,siz3=r2-l2+1;
tree a=split(1,l1-1);cut(a);
tree b=split(1,siz1);cut(b);
tree c=split(1,siz2);cut(c);
tree d=split(1,siz3),e=cut(d);
merge(a,d),merge(a,c),merge(a,b),merge(a,e);
root=a;
}
inline tree insert(int val){
if(!root)return root=new node(val,NULL);
if(root->ch[1])
{
adjust(root,1,1);
return Splay(root->ch[1]->ch[1]=new node(val,root->ch[1]));
}
return Splay(root->ch[1]=new node(val,root));
}
inline void print(){_print(root);}
inline void _print(tree x){
if(!x)return ;
pushdown(x);
_print(x->ch[0]);
pi(x->val,' ');
_print(x->ch[1]);
}
inline tree build(int l,int r,int a[]){
if(l>r)return NULL;
int mid=(l+r)>>1;
tree x=new node(a[mid],NULL);
connect(build(l,mid-1,a),x,0);
connect(build(mid+1,r,a),x,1);
return pushup(x),x;
}
inline void rebuild(int n,int a[]){root=build(1,n,a);}
inline void join(SplayTree &b){merge(root,b.root);}
};