算法
后缀数组
#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;
}