算法模板

算法

后缀数组

#define maxn 2010
#define maxm 2010
int wa[maxn],wb[maxn],rs[maxm];
int sa[maxn],rank[maxn],height[maxn];
#define cmp(r,a,b,l) ((r[a]==r[b])&&(r[a+l]==r[b+l]))
void da(const char *r,int n,int m){
    int *x=wa,*y=wb;
    for(int i=1;i<=m;++i)
        rs[i]=0;
    for(int i=1;i<=n;++i)
        ++rs[x[i]=r[i]];
    for(int i=2;i<=m;++i)
        rs[i]+=rs[i-1];
    for(int i=n;i>=1;--i)
        sa[rs[x[i]]--]=i;
    for(int j=1,p=0;j<=n&&p<n;j<<=1,m=p,p=0){
        for(int i=n-j+1;i<=n;++i)
            y[++p]=i;
        for(int i=1;i<=n;++i)
            if(sa[i]>j)
                y[++p]=sa[i]-j;
        for(int i=1;i<=m;++i)
            rs[i]=0;
        for(int i=1;i<=n;++i)
            ++rs[x[i]];
        for(int i=2;i<=m;++i)
            rs[i]+=rs[i-1];
        for(int i=n;i>=1;--i)
            sa[rs[x[y[i]]]--]=y[i];
        swap(x,y);
        x[sa[1]]=1;
        p=1;
        for(int i=2;i<=n;++i)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p:++p;
    }
    for(int i=1; i<=n; ++i)
        rank[sa[i]]=i;
    for(int i=1,k=0; i<=n; height[rank[i++]]=(k?k--:k))
        for(int j=sa[rank[i]-1]; r[i+k]==r[j+k]; ++k);
}

自动机

后缀自动机
#define maxn 2000010    //2n-1
int root=1,tot=1;
char s[maxn];
int link[maxn],ch[maxn][30];
int last=1,len[maxn];
void ins(int x) {
    int p=last,np=++tot;
    last=np,len[np]=len[p]+1;
    for(; p&&!ch[p][x]; p=link[p])
        ch[p][x]=np;
    if(p==0)
        link[np]=1;
    else {
        int q=ch[p][x];
        if(len[q]==len[p]+1)
            link[np]=q;
        else {
            int nq=++tot;
            len[nq]=len[p]+1;
            memcpy(ch[nq],ch[q],sizeof(ch[q]));
            link[nq]=link[q];
            link[q]=link[np]=nq;
            for(;ch[p][x]==q; p=link[p])
                ch[p][x]=nq;
        }
    }
}
int t[maxn],rs[maxn];
void build(){
    const int n=strlen(s);
    for(int i=0;s[i];i++)
        ins(s[i]-'a');
    for(int i=1;i<=tot;i++)
        rs[len[i]]++;
    for(int i=n;i>=0;i--)
        rs[i]+=rs[i+1];
    for(int i=1;i<=tot;i++)
        t[rs[len[i]]--]=i;
}
int runs(const char *s){
    int cur=1,lens=0,ret=0;
    for(int i=0;s[i];i++){
        int x=s[i]-'a';
        if(ch[cur][x]){
            ++lens;
            cur=ch[cur][x];
        }else{
            while(cur&&!ch[cur][x])
                cur=link[cur];
            if(!cur){
                cur=1,lens=0;
            }else{
                lens=len[cur]+1;
                cur=ch[cur][x];
            }
        }
        ret=max(ret,lens);
    }
    return ret;
}
AC自动机
const int k=26;
struct node {
    node* ch[k],*fail;
    int match;
    void clear() {memset(this,0,sizeof(node));}
};
struct ACAutomaton {
    static const int maxn=500100;
    node nodes[maxn],*root,*superRoot,*cur,*que[maxn];
    ACAutomaton() {
        clear();
    }
    node *newNode() {
        cur->clear();
        return cur++;
    }
    void clear() {
        cur=nodes;
        superRoot=newNode();
        root=newNode();
        root->fail=superRoot;
        for(int i=0; i<k; i++)
            superRoot->ch[i]=root;
        superRoot->match=-1;
    }
    void insert(const char *s) {
        node *t=root;
        for(; *s; ++s) {
            int x=*s-'a';
            if(t->ch[x]==NULL)
                t->ch[x]=newNode();
            t=t->ch[x];
        }
        t->match++;
    }
    void build() {
        int st=0,ed=0;
        que[ed++]=root;
        while(st!=ed) {
            node*t=que[st++];
            for(int i=0; i<k; i++) {
                if(t->ch[i]) {
                    t->ch[i]->fail=t->fail->ch[i];
                    que[ed++]=t->ch[i];
                } else
                    t->ch[i]=t->fail->ch[i];
            }
        }
    }
    int run(const char *s) {
        int ans=0;
        for(node *t=root; *s ; ++s) {
            int x=*s-'a';
            t=t->ch[x];
            for(node*u=t; u->match!=-1; u=u->fail)
                ans+=u->match;
        }
        return ans;
    }
};

网络流

最大流
ISAP
#define maxm 100010
#define maxn 10010
#define INF 2147483647
struct edge{
    int from,to,flow,next;
};
class ISap{
    int n,s,t,len;
    int dis[maxn],cur[maxn],p[maxn],num[maxn],q[maxn];
    bool vis[maxn];
    inline bool rev_bfs(void){
        memset(vis,0,sizeof vis);
        int st=1,ed=2;
        q[st]=t;
        dis[t]=0;
        vis[t]=1;
        while(st!=ed){
            int x=q[st];
            ++st;
            for(int i=head[x];i;i=edges[i].next){
                edge &e=edges[i^1];
                if(!vis[e.from]&&e.flow>0){
                    vis[e.from]=1;
                    dis[e.from]=dis[x]+1;
                    q[ed]=e.from;
                    ed++;
                }
            }
        }
        return vis[s];
    }
    inline int augment(){
        int x=t,mx=INF;
        while(x!=s){
            edge &e=edges[p[x]];
            mx=min(mx,e.flow);
            x=e.from;
        }
        x=t;
        while(x!=s){
            edges[p[x]].flow-=mx;
            edges[p[x]^1].flow+=mx;
            x=edges[p[x]].from;
        }
        return mx;
    }
public:
    int head[maxn];
    edge edges[maxm<<1];
    inline void clear(){
        memset(head,0,sizeof head);
        len=1;
    }
    inline ISap():len(1){
        memset(head,0,sizeof head);
    }
    inline void ins(int from,int to,int flow,int rev=0){
        edges[++len]=(edge){from,to,flow,head[from]};
        head[from]=len;
        edges[++len]=(edge){to,from,rev,head[to]};
        head[to]=len;
    }
    inline int max_flow(int s,int t,int n){
        this->s=s,this->t=t,this->n=n;
        if(!rev_bfs())
            return 0;
        memset(num,0,sizeof num);
        for(int i=0;i<n;i++){
            ++num[dis[i]];
            cur[i]=head[i];
        }
        int x=s,flow=0;
        while(dis[s]<n){
            if(x==t){
                flow+=augment();
                x=s;
            }
            bool tf=false;
            for(int &i=cur[x];i;i=edges[i].next){
                edge &e=edges[i];
                if(e.flow>0&&dis[x]==dis[e.to]+1){
                    tf=true;
                    p[e.to]=i;
                    x=e.to;
                    break;
                }
            }
            if(!tf){
                int mx=n-1;
                for(int i=head[x];i;i=edges[i].next){
                    edge &e=edges[i];
                    if(e.flow>0)
                        mx=min(mx,dis[e.to]);
                }
                if(--num[dis[x]]==0)
                    break;
                ++num[dis[x]=mx+1];
                cur[x]=head[x];
                if(x!=s)
                    x=edges[p[x]].from;
            }
        }
        return flow;
    }
};
费用流
最小费用最大流
MCMF
class MCMF{
    static const int INF=2147483647;
    static const int N=5010;
    static const int M=50010;
    int n,s,t,len;
    struct edge {
        int from,to,flow,cost,next;
    }edges[M<<1];
    int head[N];
    bool vis[N];
    int d[N];
    int p[N];
    int f[N];
    bool SPFA(int &flow,int &cost) {
        for(int i=0; i<n; i++)
            d[i]=INF;
        memset(vis,0,sizeof(vis));
        d[s]=0;
        vis[s]=1;
        p[s]=0;
        f[s]=INF;
        deque<int> q;
        q.push_back(s);
        while(!q.empty()) {
            int u=q.front();
            q.pop_front();
            vis[u]=false;
            for(int i=head[u]; i; i=edges[i].next) {
                edge& e=edges[i];
                if(e.flow && d[e.to]>d[u]+e.cost) {
                    d[e.to]=d[u]+e.cost;
                    p[e.to]=i;
                    f[e.to]=min(f[u],e.flow);
                    if(!vis[e.to]) {
                        vis[e.to]=true;
                        if(q.empty())
                            q.push_back(e.to);
                        else{
                            int tmp=q.front();
                            if(d[e.to]<d[tmp])
                                q.push_front(e.to);
                            else
                                q.push_back(e.to);
                        }
                    }
                }
            }
        }
        if(d[t]==INF)
            return false;
        flow+=f[t];
        cost+=d[t]*f[t];
        int u=t;
        while(u!=s) {
            edges[p[u]].flow-=f[t];
            edges[p[u]^1].flow+=f[t];
            u=edges[p[u]].from;
        }
        return true;
    }
public:
    MCMF(void) {
        len=1;
        memset(head,0,sizeof(head));
    }
    void ins(int from,int to,int cap,int cost,int rev=0) {
        edges[++len]=(edge) {
            from,to,cap,cost,head[from]
        };
        head[from]=len;
        edges[++len]=(edge) {
            to,from,rev,-cost,head[to]
        };
        head[to]=len;
    }
    int flows(int s,int t,int n) {
        this->s=s,this->t=t,this->n=n;
        int flow=0,cost=0;
        while(SPFA(flow,cost));
        printf("%d %d\n",flow,cost);
        return cost;
    }
};

数据结构

平衡树

伸展树(Splay)

指针+内存池+前驱后继+排名

struct node{
    int size,data,n;
    node *fa,*ch[2];
    inline node(int d=0,node *f=NULL):data(d),size(1),n(1),fa(f){
        ch[0]=ch[1]=NULL;
    }
    inline void up(){
        size=n;
        if(ch[0]) size+=ch[0]->size;
        if(ch[1]) size+=ch[1]->size;
    }
    friend inline node* max(node *a,node *b){
        if(a==NULL) return b;
        if(b==NULL) return a;
        return a->data>b->data?a:b;
    }
    friend inline node* min(node *a,node *b){
        if(a==NULL) return b;
        if(b==NULL) return a;
        return a->data<b->data?a:b;
    }
};
#define which(p) (p->fa->ch[1]==p)
struct Splay{
    static const int maxn=200010;
    static const int INF=2147483647;
    int top;
    node *root;
    node *pool[maxn<<1];
    inline Splay():top(0){
        for(int i=0;i<maxn;i++)
            pool[i]=new node();
    }
    inline void newnode(node *&p,int data,node *fa){
        p=pool[top++];
        *p=node(data,fa);
    }
    inline void dels(node *&p){
        pool[--top]=p;
        p=NULL;
    }
    inline node* &down(node *&p,int x){
        if(x==p->data)
            return p;
        return p->ch[x>p->data];
    }
    inline void rotate(node *p){
        int t=which(p);
        node *f=p->fa;
        if(f->ch[t]=p->ch[t^1])
            p->ch[t^1]->fa=f;
        if(p->fa=f->fa)
            p->fa->ch[which(f)]=p;
        f->fa=p;p->ch[t^1]=f;
        f->up();p->up();
        if(p->fa==NULL)
            root=p;
    }
    inline void splay(node *p,node *Fa){
        for(;p->fa!=Fa;rotate(p))
            if(p->fa->fa!=Fa)
                rotate(which(p)==which(p->fa)?p->fa:p);
    }
    inline node* find(node *p,int val){
        while(p){
            node *t=down(p,val);
            if(t==p){
                splay(p,NULL);
                return p;
            }
            p=t;
        }
        return NULL;
    } inline node* find(int val){return find(root,val);}
    inline void insert(node *p,int val){
        if(root==NULL){
            newnode(root,val,NULL);
            return ;
        }
        node *fa=p->fa;
        while(p!=NULL){
            node *t=down(p,val);
            if(t==p)
                break;
            fa=p;p=t;
        }
        if(p==NULL){
            newnode(p,val,fa);
            down(fa,val)=p;
        }else
            ++p->n;
        splay(p,NULL);
    } inline void insert(int val){insert(root,val);}
    inline node* begin(node *p){
        if(p==NULL)
            return NULL;
        while(p->ch[0])
            p=p->ch[0];
        return p;
    } inline node* begin(){return begin(root);}
    inline node* end(node *p){
        if(p==NULL)
            return NULL;
        while(p->ch[1])
            p=p->ch[1];
        return p;
    } inline node* end(){return end(root);}
    inline node *merge(node *a,node *b){
        if(b==NULL) return a;
        if(a==NULL) return b;
        node *t=end(a);
        splay(t,NULL);
        t->ch[1]=b;
        b->fa=t;
        t->up();
        return t; 
    }
    inline void del(node *p,int val){
        node *pos=find(root,val);
        if(pos==NULL)
            return ;
        if(pos->n>1){
            --pos->n;
            return;
        }
        pos=root;
        dels(root);
        root=merge(pos->ch[0],pos->ch[1]);
        if(root!=NULL)
            root->fa=NULL;
    } inline void del(int val){del(root,val);}
    inline int rank(node *p,int val){
        p=find(p,val);
        if(p==NULL) return -1;
        if(p->ch[0]==NULL)
            return 1;
        return p->ch[0]->size+1;
    } inline int rank(int val){return rank(root,val);}
    inline node* kth(node *p,int k){
        while(p){
            int d=p->ch[0]?p->ch[0]->size:0;
            if(k>=d+1&&k<=d+p->n){
                splay(p,NULL);
                return p;
            }
            if(k<d+1) p=p->ch[0];
            else k-=d+p->n,p=p->ch[1];
        }
        return NULL;
    } inline node* kth(int k){return kth(root,k);}
    inline node* pre(node* p,int val) {
        node *ret=NULL;
        while(p!=NULL) {
            int tcmp=val>p->data;
            if(tcmp)
                ret=max(ret,p);
            p=p->ch[tcmp];
        }
        return ret;
    } inline node* pre(int val){return pre(root,val);}
    inline node* nxt(node* p,int val) {
        node *ret=NULL;
        while(p!=NULL) {
            int tcmp=val<p->data;
            if(tcmp)
                ret=min(ret,p);
            p=p->ch[tcmp^1];
        }
        return ret;
    } inline node* nxt(int val){return nxt(root,val);}
};
替罪羊树

无父指针+内存池+指针

#include<bits/stdc++.h>
using namespace std;
namespace Scapegoat_Tree {
    static const int MAXN=100010;
    const double alpha=0.75;
    struct node {
        node *ch[2];
        int key,size,cover; // size为有效节点的数量,cover为节点总数量
        bool exist; // 是否存在(即是否被删除)
        void PushUp(void) {
            size=ch[0]->size+ch[1]->size+(int)exist;
            cover=ch[0]->cover+ch[1]->cover+1;
        }
        bool isBad(void) { // 判断是否需要重构
            return ((ch[0]->cover>cover*alpha+5)||(ch[1]->cover>cover*alpha+5));
        }
    };
    struct STree {
        protected:
            node mem_poor[MAXN]; //内存池,直接分配好避免动态分配内存占用时间
            node *tail,*root,*null; // 用null表示NULL的指针更方便,tail为内存分配指针,root为根
            node *bc[MAXN];
            int bc_top; // 储存被删除的节点的内存地址,分配时可以再利用这些地址
            node *newnode(int key) {
                node *p=bc_top ? bc[--bc_top] : tail++;
                p->ch[0]=p->ch[1]=null;
                p->size=p->cover=1;
                p->exist=true;
                p->key=key;
                return p;
            }
            void travel(node *p,vector<node *>&v) {
                if(p == null) return;
                travel(p->ch[0],v);
                if(p->exist) v.push_back(p); // 构建序列
                else bc[bc_top++]=p; // 回收
                travel(p->ch[1],v);
            }
            node *divide(vector<node *>&v,int l,int r) {
                if(l >= r)
                return null;
                int mid=(l+r) >> 1;
                node *p=v[mid];
                p->ch[0]=divide(v,l,mid);
                p->ch[1]=divide(v,mid+1,r);
                p->PushUp(); // 自底向上维护,先维护子树
                return p;
            }
            void rebuild(node *&p) {
                static vector<node *>v;
                v.clear();
                travel(p,v);
                p=divide(v,0,v.size());
            }
            node **insert(node *&p,int val) {
                if(p == null) {
                    p=newnode(val);
                    return &null;
                } else {
                    p->size++;
                    p->cover++;
                    node **res=insert(p->ch[val >= p->key],val);// 返回值储存需要重构的位置,若子树也需要重构,本节点开始也需要重构,以本节点为根重构
                    if(p->isBad()) res=&p;
                    return res;
                }
            }
            void erase(node *p,int id) {
                p->size--;
                int offset=p->ch[0]->size+p->exist;
                if(p->exist && id == offset) {
                    p->exist=false;
                    return;
                } else {
                    if(id <= offset) erase(p->ch[0],id);
                    else erase(p->ch[1],id - offset);
                }
            }
        public:
            void init(void) {
                tail=mem_poor;
                null=tail++;
                null->ch[0]=null->ch[1]=null;
                null->cover=null->size=null->key=0;
                root=null;
                bc_top=0;
            }
            STree(void) {
                init();
            }
            void Insert(int val) {	//插入val 
                node **p=insert(root,val);
                if(*p!=null) rebuild(*p);
            }
            int rank(int val) {	//val的排名 
                node *now=root;
                int ans=1;
                while(now!=null) { // 非递归求排名
                    if(now->key >= val) now=now->ch[0];
                    else {
                        ans += now->ch[0]->size+now->exist;
                        now=now->ch[1];
                    }
                }
                return ans;
            }
            int kth(int k) { // 第K大的数 
                node *now=root;
                while(now!=null) {
                    if(now->ch[0]->size+1 == k && now->exist) return now->key;
                    else if(now->ch[0]->size >= k) now=now->ch[0];
                    else k-=now->ch[0]->size+now->exist,now=now->ch[1];
                }
            }
            void erase(int k) {	//删除数值k 
                erase(root,rank(k));
                if(root->size<alpha*root->cover)
                    rebuild(root);
            }
            void erase_kth(int k) {	//删除第k大 
                erase(root,k);
                if(root->size<alpha*root->cover)
                    rebuild(root);
            }
            int prv(int k){//前驱 
            	int t=rank(k);
            	return t!=1?kth(t-1):-1;
            }
            int sub(int k){//后继 
            	int t=rank(k);
            	return t!=root->size?kth(t+1):-1;
            }
    };
}
using namespace Scapegoat_Tree;
STree t;
#define maxn 10010
int s[maxn];
int main(void)
{
	srand(time(0));
	t.init();
	for(int i=1;i<=maxn;i++)
		s[i]=i;
	random_shuffle(s+1,s+1+maxn);
	for(int i=1;i<=maxn;i++)
		t.Insert(s[i]);
	for(int i=1;i<=maxn;i++){
		int ss=t.sub(i);
		if(ss!=i+1)
			printf("%d %d\n",i,ss);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值