数据结构
普通堆、可删堆
struct Node{
__attribute__((always_inline))inline int operator < (const Node &o){}
__attribute__((always_inline))inline int operator == (const Node &o){}
};
__attribute__((always_inline))inline void swap(Node &a,Node &b){}
struct Heap{
Node a[N];
int size;
inline void push(const Node &x){
int i=++size,fa;a[size]=x;
while(i>1){
fa=i>>1;
if(a[fa]<a[i]) return;
swap(a[fa],a[i]);i=fa;
}
}
inline void pop(){
int i=1,ls,rs;a[1]=a[size--];
while((i<<1)<=size){
ls=i<<1;rs=ls|1;
if(rs<=size&&a[rs]<a[ls]) ls=rs;
if(a[i]<a[ls]) return;
swap(a[ls],a[i]);i=ls;
}
}
};
struct DeletableHeap{
Heap ins,dele;
inline Node top(){while(dele.size&&ins.a[1]==dele.a[1]) ins.pop(),dele.pop();return ins.a[1];}
inline void pop(){while(dele.size&&ins.a[1]==dele.a[1]) ins.pop(),dele.pop();ins.pop();}
__attribute__((always_inline))inline void push(const Node &x){ins.push(x);}
__attribute__((always_inline))inline void del(const Node &x){dele.push(x);}
__attribute__((always_inline))inline void clear(){ins.size=dele.size=0;}
__attribute__((always_inline))inline int size(){return ins.size-dele.size;}
__attribute__((always_inline))inline int empty(){return ins.size==dele.size;}
};
使用自定义函数重载 std::set
,std::priority_queue
等的比较
函数指针
inline int pqueCmp(const int &a,const int &b){return a>b;}
std::priority_queue<int,std::vector<int>,int(*)(const int &a,const int &b)>pque(pqueCmp);
lambda 函数
auto pqueCmp=[](const int &a,const int &b){return a>b;};
std::priority_queue<int,std::vector<int>,decltype(pqueCmp)>pque(pqueCmp);
这样写有时候莫名奇妙的 RE???
并查集
int fa[N];
int find(int k){return fa[k]==k?k:fa[k]=find(fa[k]);}
inline void link(int x,int y){
x=find(x);y=find(y);
if(x!=y) fa[x]=y;
}
树状数组
int tree[N];
#define lowbit(x) (x&(-x))
inline void add(int pos,int k){for(;pos<=n;pos+=lowbit(pos)) tree[pos]+=k;}
inline int ask(int pos){
int ans=0;
for(;pos;pos-=lowbit(pos)) ans+=tree[pos];
return ans;
}
线段树
struct Node{
Node *ls,*rs;
int tag;
inline void pushup(){}
inline void pushdown(){}
}dizhi[N*2],*root=&dizhi[0];int tot=0;
void build(Node *&tree,int l,int r){
tree=&dizhi[++tot];
if(l==r) return;
int mid=(l+r)>>1;
build(tree->ls,l,mid);build(tree->rs,mid+1,r);
tree->pushup();
}
void change(Node *tree,int l,int r,int pos){
if(l==r) return;
tree->pushdown();
int mid=(l+r)>>1;
pos<=mid?change(tree->ls,l,mid,pos):change(tree->rs,mid+1,r,pos);
tree->pushup();
}
void change(Node *tree,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return;
tree->pushdown();
int mid=(l+r)>>1;
if(ql<=mid) change(tree->ls,l,mid,ql,qr,k);
if(qr>mid) change(tree->rs,mid+1,r,ql,qr,k);
tree->pushup();
}
Data ask(Node *tree,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return tree->x;
tree->pushdown();
int mid=(l+r)>>1;
if(qr<=mid) return ask(tree->ls,l,mid,ql,qr);
if(ql>mid) return ask(tree->rs,mid+1,r,ql,qr);
return ask(tree->ls,l,mid,ql,qr)+ask(tree->rs,mid+1,r,ql,qr);
}
简单平衡树
std::set
替罪羊树
#define alpha 0.7
struct Node{
Node *ls,*rs;
int val,cnt,size;//size:num of not deleted,cnt:all
int deleted;
inline void pushup(){}
}*null,*root,*nodes[1100005],**badtag;
int nodeNum;
inline int isbad(Node *tree){return tree->ls->cnt>alpha*tree->cnt+5||tree->rs->cnt>alpha*tree->cnt+5;}
void dfs(Node *tree){
if(tree==null) return;
dfs(tree->ls);
if(!tree->deleted) nodes[++nodeNum]=tree;
dfs(tree->rs);
if(tree->deleted) delete tree;
}
Node *build(int l,int r){
if(l>r) return null;
if(l==r){
nodes[l]->ls=nodes[l]->rs=null;
nodes[l]->cnt=nodes[l]->size=1;
return nodes[l];
}
int mid=(l+r)>>1;
Node *tree=nodes[mid];
tree->ls=build(l,mid-1);tree->rs=build(mid+1,r);
tree->pushup();
return tree;
}
inline void rebuild(Node *&tree){
nodeNum=0;
dfs(tree);
tree=build(1,nodeNum);
}
void insert(Node *&tree,int x){
if(tree==null){
tree=new Node;
tree->ls=tree->rs=null;
tree->deleted=0;tree->val=x;
tree->size=tree->cnt=1;
return;
}
tree->size++;tree->cnt++;
if(x>tree->val) insert(tree->rs,x);
else insert(tree->ls,x);
if(isbad(tree)) badtag=&tree;
}
inline void Insert(Node *&tree,int x){
badtag=&null;
insert(tree,x);
if(badtag!=&null) rebuild(*badtag);
}
inline int rank(Node *tree,int x){
int ans=1;
while(tree!=null){
if(x<=tree->val) tree=tree->ls;
else{
ans+=tree->ls->size+!tree->deleted;
tree=tree->rs;
}
}
return ans;
}
inline int kth(tr *tree,int rk){
while(tree!=null){
if(!tree->deleted&&tree->ls->size+1==rk) return tree->val;
if(rk<=tree->ls->size) tree=tree->ls;
else{
rk-=tree->ls->size+!tree->deleted;
tree=tree->rs;
}
}
}
void erase(tr *tree,int rk){
if(!tree->deleted&&rk==tree->ls->size+1){
tree->deleted=1;
tree->size--;
return;
}
tree->size--;
if(rk<=tree->ls->size+!tree->deleted) erase(tree->ls,rk);
else erase(tree->rs,rk-tree->ls->size-!tree->deleted);
}
fhq-treap
struct Node{
Node *ls,*rs;
int val,rnd,size;
inline void pushup(){size=1+ls->size+rs->size;}
}*root,*null;
inline void init(Node *x){x->ls=x->rs=null;x->size=1;x->rnd=rand();}
inline void init(){
srand(822);
null=new Node;null->ls=null->rs=null;null->size=0;null->val=INT_INF;
root=null;
}
void split(Node *tree,int k,Node *&L,Node *&R){
if(tree==null) return L=R=null,void();
if(tree->ls->size>=k){
R=tree;
split(tree->ls,k,L,R->ls);
R->pushup();
}
else{
L=tree;
split(tree->rs,k-tree->ls->size-1,L->rs,R);
L->pushup();
}
}
Node* merge(Node *L,Node *R){
if(L==null) return R;
if(R==null) return L;
if(L->rnd<R->rnd){
L->rs=merge(L->rs,R);
return L->pushup(),L;
}
else{
R->ls=merge(L,R->ls);
return R->pushup(),R;
}
}
inline int rank(int val){
int ans=1;
Node *tree=root;
while(tree!=null){
if(val<=tree->val) tree=tree->ls;
else{
ans+=tree->ls->size+1;
tree=tree->rs;
}
}
return ans;
}
inline void insert(int val){
int rk=rank(val)-1;
Node *x,*y;
split(root,rk,x,y);
Node *a=new Node;init(a);a->val=val;
root=merge(merge(x,a),y);
}
inline void del(int val){
int rk=rank(val);
Node *x,*y,*z;
split(root,rk,x,z);
split(x,rk-1,x,y);//y->val=val,y->size=1
root=merge(x,z);
delete y;
}
inline int kth(int k){
Node *x,*y,*z;
split(root,k-1,x,y);
split(y,1,y,z);
root=merge(x,merge(y,z));
return y->val;
}
link-cut-tree
struct LCT{
struct Node{
Node *son[2],*fa;
int val,res;
int tag;
}dizhi[N],*null;
inline void init(){null=&dizhi[0];}
#define ident(tree,fa) (fa->son[1]==tree)
#define notroot(tree) (tree->fa->son[0]==tree||tree->fa->son[1]==tree)
#define pushup(tree) (tree->res=tree->son[0]->res^tree->son[1]->res^tree->val)
inline void connect(Node *tree,Node *fa,int k){fa->son[k]=tree;tree->fa=fa;}
inline void pushdown(Node *tree){
if(!tree->tag) return;
tree->tag=0;
tree->son[0]->tag^=1;tree->son[1]->tag^=1;
std::swap(tree->son[0],tree->son[1]);
}
inline void rotate(Node *tree){
Node *fa=tree->fa,*faa=fa->fa;
pushdown(fa);pushdown(tree);
int k=ident(tree,fa);
connect(tree->son[k^1],fa,k);
tree->fa=faa;
if(notroot(fa)) faa->son[ident(fa,faa)]=tree;
connect(fa,tree,k^1);
pushup(fa);pushup(tree);
}
inline void splay(Node *tree){
Node *fa=tree->fa,*faa=fa->fa;
while(notroot(tree)){
fa=tree->fa;faa=fa->fa;
if(notroot(fa)) rotate((ident(tree,fa)^ident(fa,faa))?tree:fa);
rotate(tree);
}
}
inline void access(Node *x){
for(Node *lastx=null;x!=null;lastx=x,x=x->fa){
pushdown(x);splay(x);x->son[1]=lastx;pushup(x);
}
}
inline void makeroot(Node *x){access(x);splay(x);x->tag^=1;}
inline Node* findroot(Node *x){
access(x);splay(x);pushdown(x);
while(x->son[0]!=null) x=x->son[0],pushdown(x);
splay(x);return x;
}
inline void link(Node *x,Node *y){makeroot(x);if(findroot(y)!=x) x->fa=y;}
inline void cut(Node *x,Node *y){
makeroot(x);
if(findroot(y)!=x||y->fa!=x||y->son[0]!=null) return;
y->fa=x->son[1]=null;pushup(x);
}
inline Node* split(Node *x,Node *y){makeroot(x);access(y);splay(y);return y;}
inline Node* Split(int x,int y){return split(&dizhi[x],&dizhi[y]);}
inline void Link(int x,int y){link(&dizhi[x],&dizhi[y]);}
inline void Cut(int x,int y){cut(&dizhi[x],&dizhi[y]);}
inline void Change(int o,int val){Node *x=&dizhi[o];splay(x);x->val=val;pushup(x);}
};
bitset
struct Bitset{
#define W 63
unsigned long long *a;
int size;
inline Bitset(){size=0;}
inline ~Bitset(){if(size) delete []a;}
inline void resize(const int &s){
if(size) delete []a;
size=(s+W)>>6;
a=new unsigned long long[size];
}
inline void reset(){__builtin_memset(a,0,size*sizeof(a[0]));}
inline void set(){__builtin_memset(a,255,size*sizeof(a[0]));}
inline int operator [] (const int &pos)const{return (a[pos>>6]>>(pos&W))&1;}
inline void operator = (const Bitset &o){resize(o.size<<6);__builtin_memcpy(a,o.a,size*sizeof(a[0]));}
inline void set(const int &pos,const int &val){a[pos>>6]&=~(1ull<<(pos&W));a[pos>>6]|=((unsigned long long)val<<(pos&W));}
inline int count(){
int ans=0;
for(int i=0;i<size;i++) ans+=__builtin_popcountll(a[i]);
return ans;
}
inline Bitset operator ^ (const Bitset &o)const{
Bitset ans;ans=*this;
for(int i=0;i<size;i++) ans.a[i]^=o.a[i];
return ans;
}
inline Bitset operator | (const Bitset &o)const{
Bitset ans;ans=*this;
for(int i=0;i<size;i++) ans.a[i]|=o.a[i];
return ans;
}
inline Bitset operator & (const Bitset &o)const{
Bitset ans;ans=*this;
for(int i=0;i<size;i++) ans.a[i]&=o.a[i];
return ans;
}
inline void operator ^= (const Bitset &o){for(int i=0;i<size;i++) a[i]^=o.a[i];}
inline void operator |= (const Bitset &o){for(int i=0;i<size;i++) a[i]|=o.a[i];}
inline void operator &= (const Bitset &o){for(int i=0;i<size;i++) a[i]&=o.a[i];}
inline Bitset operator ~ ()const{
Bitset ans;ans=*this;
for(int i=0;i<size;i++) ans.a[i]=~ans.a[i];
return ans;
}
inline Bitset operator >> (int bit){
Bitset ans;ans=*this;
int o=bit>>6;bit&=W;
if(o) for(int i=0;i+o<size;i++) ans.a[i]=a[i+o];
for(int i=size-o;i<size;i++) ans.a[i]=0;
if(!bit) return ans;
int S=(1ull<<bit)-1;
for(int i=0;i<size-1;i++) ans.a[i]>>=bit,ans.a[i]|=(ans.a[i+1]&S)<<(W+1-bit);
ans.a[size-1]>>=bit;
return ans;
}
#undef W
};
双模哈希
#define HASH_MOD1 1000000007
#define HASH_MOD2 1000000009
#define HASH_BASE 822
struct Hash{
unsigned long long a,b;
inline void operator = (const unsigned long long &o){a=b=o;}
inline Hash operator + (const Hash &o){return (Hash){(a+o.a)%HASH_MOD1,(b+o.b)%HASH_MOD2};}
inline Hash operator - (const Hash &o){return (Hash){(a-o.a+HASH_MOD1)%HASH_MOD1,(b-o.b+HASH_MOD2)%HASH_MOD2};}
inline Hash operator * (const unsigned long long &o){return (Hash){a*o%HASH_MOD1,b*o%HASH_MOD2};}
inline int operator == (const Hash &o){return a==o.a&&b==o.b;}
inline int operator != (const Hash &o){return a!=o.a||b!=o.b;}
inline int operator < (const Hash &o)const{return a==o.a?b<o.b:a<o.a;}
inline unsigned __int128 toUint128(){return (unsigned __int128)a*_ULL_MAX+b;}
};