模版
数据结构
vector
template<typename Tp>
struct Vector{
Tp *arr=new Tp[1+5]; int siz_,cap_=1;
void allocate(){
Tp *new_arr=new Tp[(cap_<<1)+5];
for(int i=0;i<cap_;i++)new_arr[i]=arr[i];
arr=new_arr,cap_<<=1;
}int size(){ return siz_; }
void push_back(Tp x){
if(siz_==cap_)allocate();
arr[siz_++]=x;
}Tp& operator[](const Tp &x)const{
return arr[x];
}Tp *begin(){ return arr; }
Tp *end(){ return (arr+siz_); }
void insert(int x,Tp val){
if(siz_==cap_)allocate();
for(int i=siz_-1;i>=x;i--)arr[i+1]=arr[i];
siz_++,arr[x]=val;
}
};
实现了 \(vector\) 最基础的功能,比 \(STL\) 稍快。
deque
template<typename Tp,int SIZ>
struct Deque{
Tp q[SIZ+5]; int f=1,b=0;
void push_back(Tp x){ q[++b]=x; }
void pop_back(Tp x){ b--; }
void pop_front(){ f++; }
Tp front(){ return q[f]; }
Tp back(){ return q[b]; }
bool empty(){ return (f>b); }
int size(){ return b-f+1; }
};
可用于单调队列。
stack
template<typename Tp,int SIZ>
struct Stack{
Tp s[SIZ+5]; int t;
void push(Tp x){ s[++t]=x; }
void pop(Tp x){ t--; }
Tp top(){ return s[t]; }
bool empty(){ return (!t); }
int size(){ return t; }
};
queue
template<typename Tp,int SIZ>
struct Queue{
Tp q[SIZ+5]; int f=1,b;
void push(Tp x){ q[b=b%(SIZ+1)+1]=x; }
void pop(){ f=f%(SIZ+1)+1; }
Tp front(){ return q[f]; }
Tp back(){ return q[b]; }
bool empty(){ return (b+1==f); }
int size(){ return (b-f+2+SIZ)%(SIZ+1); }
};
循环队列,可用于 \(SPFA\)。
并查集
template<int SIZ>
struct DisJoint_Set{
int f[SIZ+5];
void clear(){ for(int i=1;i<=SIZ;i++)f[i]=i; }
int find(int x){ return (f[x]==x)?x:f[x]=find(f[x]); }
void merge(int x,int y){ f[find(x)]=find(y); }
};
路径压缩并查集。
template<int SIZ>
struct DisJoint_Set{
int f[SIZ+5]; bool val[SIZ+5];
void clear(){
for(int i=1;i<=SIZ;i++)
f[i]=i,val[i]=0;
}int find(int x){
if(f[x]==x)return x;
int fa=f[x]; f[x]=find(f[x]);
val[x]^=val[fa]^val[f[x]];
return f[x];
}void Union(int x,int y,bool b){
int fx=find(x),fy=find(y);
if(fx==fy)return; f[fx]=fy;
if(!(b^val[x]^val[y]))val[fx]=1;
}
};
带权并查集,可用于维护两个对立的集合。
BIT
template<int SIZ>
struct BIT{
int tr[SIZ+5];
inline int lowbit(int x){ return x&(-x); }
void add(int x,int val){
for(int i=x;i<=SIZ;i+=lowbit(i))
tr[i]+=val;
}int query(int x){
int ans=0;
for(int i=x;i;i-=lowbit(i))ans+=tr[i];
return ans;
}
};
单修区查树状数组.
ST表
template<int SIZ>
struct Sparse_Table{
int ST[20][SIZ+5],log[SIZ+5]={-1};
void build(){
for(int i=1;i<=SIZ;i++)log[i]=log[i>>1]+1;
for(int i=1;i<=log[SIZ];i++)
for(int j=1;j+(1<<i)<=SIZ+1;j++)
ST[i][j]=min(ST[i-1][j],ST[i-1][j+(1<<(i-1))]);
}int query(int L,int R){
int k=log[R-L+1];
return min(ST[k][L],ST[k][R-(1<<k)+1]);
}
};
哈希表
namespace HASH_TABLE{
constexpr int A=5904375,B=5098475,M=1e6+3,P=1e9+7;
struct Hash_Table{
struct E{ int x,val,last; }e[M];
int head[M],cnt;
int get_hash(int x){ return (1ll*A*x+B)%P%M; }
int at(int x){
int y=get_hash(x);
for(int i=head[y];i;i=e[i].last)
if(e[i].x==x)return e[i].val;
return 0;
}void insert(int x,int val){
int y=get_hash(x);
for(int i=head[y];i;i=e[i].last)
if(e[i].x==x){ e[i].val=val; return; }
e[++cnt].x=x,e[cnt].val=val;
e[cnt].last=head[y],head[y]=cnt;
}
struct BOBO{
Hash_Table &h; int x;
BOBO(Hash_Table &hh,int xx):h(hh),x(xx){}
int operator=(int val){ h.insert(x,val); return val; }
operator int(){ return h.at(x); }
};
BOBO operator[](int x){ return BOBO(*this,x); }
};
}using HASH_TABLE::Hash_Table;
可以像数组一样使用.
template<typename Key,typename Val>
struct Hash_Table{
struct E{ Key x; Val val; int last; }e[N];
int head[M],cnt;
int get_hash(Key x){ return x.hash()%M; }
void insert(Key x,Val v){
int y=get_hash(x);
for(int i=head[y];i;i=e[i].last)
if(e[i].x==x){ e[i].val=v; return; }
e[++cnt]=E{x,v,head[y]},head[y]=cnt;
}Val at(Key x){
int y=get_hash(x);
for(int i=head[y];i;i=e[i].last)
if(e[i].x==x)return e[i].val;
return 0;
}
};
更加实用的一版.
(可以动态修改桶的大小)
namespace HASH_TABLE{
int Prim[23]={11,23,47,89,211,401,809,1601,3203,6421,12809,25601,51203,102407,204803,409813,800011,1600033,3200003,6400013,12800009,25600013,51200027};
int find_(int x){
int L=-1,R=23,mid;
while(L+1<R){
mid=(L+R)>>1;
if(x<=Prim[mid])R=mid;
else L=mid;
}return R;
}
template<typename Key,typename Val>
struct Hash_Table{
static constexpr int A=234723;//随机整数
struct node{
Key x; Val v; node* to;
node(){
x=0,v=0;//这里要注意调整,这是整数的情况
to=nullptr;
}
};
node** head; int pos,tot;
Hash_Table(){
pos=tot=0; head=new node*[Prim[pos]];
for(int i=0;i<Prim[pos];i++)head[i]=nullptr;
}
void rebuild(int t){
node* arr=new node[tot]; int res=0;
for(int i=0;i<Prim[pos];i++)
for(node* s=head[i];s!=nullptr;s=s->to)arr[res++]=*s;
delete[] head; head=new node*[Prim[t]];
pos=t,tot=0;
for(int i=0;i<Prim[t];i++)head[i]=nullptr;
for(int i=0;i<res;i++)insert_(arr[i].x,arr[i].v);
delete[] arr;
}
void check_now(){
if(tot==Prim[pos])rebuild(pos+1);
}
int get_hash(Key x){//注意更改哈希函数
return 1ll*x*A%Prim[pos];
}
void insert_(Key x,Val v){
int y=get_hash(x);
for(node* t=head[y];t!=nullptr;t=t->to)
if(t->x==x){ t->v=v; return; }
node* t=new node();
t->x=x,t->v=v,t->to=head[y];
head[y]=t,tot++;
}
Val query_(Key x){
int y=get_hash(x);
for(node* t=head[y];t!=nullptr;t=t->to)
if(t->x==x)return t->v;
return 0;
}
void insert(Key x,Val v){ check_now(); insert_(x,v); }
Val query(Key x){ return query_(x); }
void resize(int siz){ rebuild(find_(siz)); }
};
}using HASH_TABLE::Hash_Table;
二叉堆
template<typename Tp>
struct Heap{
#define lch ((i)<<1)
#define rch ((i)<<1|1)
#define fa ((i)>>1)
vector<Tp> sta; int t;
void claer(){ sta.resize(1),t=0; }
bool empty(){ return t==0; }
int size(){ return t; }
Tp top(){ return sta[1]; }
void push(Tp val){
sta.push_back(val),t++;
for(int i=t;fa&&sta[i]<sta[fa];i=fa)
swap(sta[fa],sta[i]);
}void pop(){
swap(sta[1],sta[t]),sta.pop_back(),t--;
for(int i=1,to=lch;lch<=t;to=lch){
if(rch<=t&&sta[rch]<sta[lch])to=rch;
if(sta[to]<sta[i])swap(sta[i],sta[to]),i=to;
else break;
}
}
};
比 \(STL\) 优先队列快了好几倍。
bitset
template<int SIZ>
struct Bitset{
ull a[SIZ/64+5];
Bitset(){ memset(a,0,sizeof(a)); }
bool at(int x){ return (a[x/64]>>(x%64))&1ull; }
void set(int x){ a[x/64]|=(1ull<<(x%64)); }
void reset(int x){ a[x/64]&=(~(1ull<<(x%64))); }
void set(){ memset(a,-1,sizeof(a)); }
void reset(){ memset(a,0,sizeof(a)); }
struct BOBO{
Bitset<SIZ> &b; int pos;
BOBO(Bitset &bb,const int &poss):b(bb),pos(poss){}
bool operator=(bool val){ (val)?b.set(pos):b.reset(pos); return val; }
bool operator&=(bool val){ (!val)&&(b.reset(pos)); return b.at(pos); }
bool operator|=(bool val){ (val)&&(b.set(pos)); return b.at(pos); }
bool operator^=(bool val){ (val==b.at(pos))?b.reset(pos):b.set(pos); return b.at(pos); }
operator bool(){ return b.at(pos); }
};
BOBO operator[](const int &x){ return BOBO(*this,x); }
void operator^=(const Bitset<SIZ> &b){ for(int i=0;i<=SIZ/64;i++)a[i]^=b.a[i]; }
void operator&=(const Bitset<SIZ> &b){ for(int i=0;i<=SIZ/64;i++)a[i]&=b.a[i]; }
void operator|=(const Bitset<SIZ> &b){ for(int i=0;i<=SIZ/64;i++)a[i]|=b.a[i]; }
Bitset operator^(const Bitset<SIZ> &b)const{ Bitset<SIZ> a=*this,ans; for(int i=0;i<=SIZ/64;i++)ans.a[i]=a.a[i]^b.a[i]; return ans; }
Bitset operator&(const Bitset<SIZ> &b)const{ Bitset<SIZ> a=*this,ans; for(int i=0;i<=SIZ/64;i++)ans.a[i]=a.a[i]&b.a[i]; return ans; }
Bitset operator|(const Bitset<SIZ> &b)const{ Bitset<SIZ> a=*this,ans; for(int i=0;i<=SIZ/64;i++)ans.a[i]=a.a[i]|b.a[i]; return ans; }
Bitset operator~()const{ Bitset<SIZ> a=*this,ans; for(int i=0;i<=SIZ/64;i++)ans.a[i]=(~a.a[i]); return ans; }
};
算法
快读快写
struct Fast_IO{
static const int SIZ=(1<<20);
char in[SIZ],*p1,*p2;
char out[SIZ]; int p3;
char sta[30]; int top;
char gc(){ return (p1==p2)&&(p2=(p1=in)+fread(p1,1,SIZ,stdin)),(p1==p2)?EOF:(*p1++); }
void flu(){ fwrite(out,1,p3,stdout),p3=0; }
void pc(const char &ch){ (p3==SIZ)&&(flu(),0),out[p3++]=ch; }
~Fast_IO(){ flu(); }
Fast_IO& operator >>(char &ch){ do ch=gc(); while(ch==' '||ch=='\n'); return *this; }
Fast_IO& operator >>(int &x){
x=0; bool fu=0; char ch=gc();
while(!isdigit(ch))(ch=='-')&&(fu=1),ch=gc();
while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=gc();
(fu)&&(x=-x); return *this;
}Fast_IO& operator >>(char *ch){
(*ch)=gc(); while(*ch!=' '&&*ch!='\n')*(++ch)=gc();
return *this;
}
Fast_IO& operator <<(const char &ch){ pc(ch);return *this; }
Fast_IO& operator <<(int x){
(x<0)&&(pc('-'),x=-x,0);
do sta[++top]=char(x%10+'0'),x/=10; while(x);
while(top)pc(sta[top--]);
return *this;
}Fast_IO& operator <<(char *ch){
while(*ch!=' ')pc(*ch++);
return *this;
}
}fin,fout;
离散化
template<typename Tp>
void Discreteization(Tp arr_a[],int L,int R){
Tp* arr_new=new Tp[R-L+5];
for(int i=1,j=L;j<=R;i++,j++)arr_new[i]=arr_a[j];
sort(arr_new+L,arr_new+R+1);
int max_arr=unique(arr_new+L,arr_new+R+1)-arr_new-1;
for(int i=L;i<=R;i++)
arr_a[i]=lower_bound(arr_new+1,arr_new+max_arr+1,arr_a[i])-arr_new;
delete[] arr_new;
}

浙公网安备 33010602011771号