这里什么都有 😄
封装了一些数据结构和一些数学东西和一些杂项
以下是封装内容列表(更新中)
数据结构:
线段树
平衡树(FHQ-Treap)
树状数组
并查集
扩展域并查集
单调栈
珂朵莉树
可持久化线段树
数学:
逆元
exgcd
快速幂、龟速乘
gcd,lcm
阶乘预处理
逆元组合数计算
其他东西:
快读快写
矩阵
封装好的mt19937随机数生成器
质数判断
计划加入的:
各种各样的线段树
平衡树(Splay)
文艺平衡树
欧拉函数
单调队列
持续更新中
cpp
//V2.2
//Last update:2026/4/6
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/rope>
using namespace std;
using namespace __gnu_pbds;
#define ll long long
#define pii pair<int,int>
#define ull unsigned long long
#define pll pair<long long,long long>
//-------------------------------------------------//
//-****************工具函数部分********************//
//-------------------------------------------------//
//有用的一些东西
mt19937 rnd(time(NULL));
mt19937_64 rndll(time(NULL));
int random(int l,int r)
{
return rnd()%(r-l+1)+r;
}
long long randomll(long long l,long long r)
{
return rndll()%(r-l+1)+r;
}
//快读快写
namespace FastIO
{
template<typename T> inline void read(T &x)
{
x=0;
T f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
{
f=-1;
}
ch=getchar();
}
while(isdigit(ch))
{
x=x*10+(ch-'0');
ch=getchar();
}
x*=f;
}
template <typename T> void readArrayInt(T a[],long long l,long long r )
{
if(r<l)
{
swap(l,r);
}
for(int i=l;i<=r;i++)
{
read(a[i]);
}
}
template<typename T>
inline void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
template <typename T> void writeArrayInt(T a[],long long l,long long r,char split,char end)
{
if(r<l)
{
swap(l,r);
}
for(int i=l;i<=r;i++)
{
write(a[i]);
putchar(split);
}
putchar(end);
}
}
//-------------------------------------------------//
//-****************数学函数部分********************//
//-------------------------------------------------//
namespace Numeric
{
bool isprime(long long n)
{
if(n==1)
{
return 0;
}
if(n==2)
{
return 1;
}
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
return 0;
}
}
return 1;
}
bool XNOR(bool a,bool b) //逻辑同或
{
if(a==b)
{
return 1;
}
return 0;
}
template<typename T> T Gcd(T a,T b)
{
return __gcd(a,b);
}
template<typename T> T Lcm(T a,T b)
{
return __lcm(a,b);
}
template<typename T> T qpow(T a,T b,T mod=0)
{
T ans=1;
if(mod==0)
{
while(b)
{
if(b&1)
{
ans=ans*a;
}
a*=a;
b>>=1;
}
return ans;
}
while(b)
{
if(b&1)
{
ans=ans*a%mod;
}
a=a*a%mod;
b>>=1;
}
return ans;
}
template <typename T> T turtlemul(T a,T b,T mod)
{
T ans=1;
while(b)
{
if(b&1)
{
ans=(ans+a)%mod;
}
a=(a+a)%mod;
b>>=1;
}
return ans;
}
template<typename T> T InverseElement(T a,T mod) //费马小定理求逆元
{
return qpow(a,mod-2,mod);
}
template<typename T> T GetFac(T x)
{
int ans=1;
for(int i=1;i<=x;i++)
{
ans*=i;
}
return ans;
}
template<typename T> T GetFac(T x,T mod)
{
T ans=1;
for(int i=1;i<=x;i++)
{
ans*=i;
ans%=mod;
}
return x;
}
template<typename T> void InitFac(T a[],T len,T strt,T mod)
{
a[strt]=1;
for(int i=2;i<=len;i++)
{
a[strt+i-1]=(a[strt+i-2]*i)%mod;
}
}
template<typename T> C(T n,T m,T p,T f[])
{
if(n<m)
{
return 0;
}
return f[n]*qpow(f[n-m],p-2,p)%p*qpow(f[m],p-2,p)%p;
}
template<typename T> T exgcd(T a,T b,T &x,T &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
T r=exgcd(b,a%b,y,x);
y-=a/b*x;
return r;
}
}
namespace DataStructures
{
template <typename T> T lowbit(T x)
{
return ((x)&(-(x)));
}
//-------------------------------------------------//
//-****************数据结构部分********************//
//-------------------------------------------------//
//珂朵莉树
#define ODT ChthollyTree
struct ChthollyTree_Treenode
{
int l,r;
mutable int v;
ChthollyTree_Treenode(int L=0,int R=0,int V=0)
{
l=L,r=R,v=V;
}
bool operator < (const ChthollyTree_Treenode &x) const
{
return l<x.l;
}
};
struct ChthollyTree
{
set<ChthollyTree_Treenode>s;
set<ChthollyTree_Treenode>::iterator split(int pos)
{
set<ChthollyTree_Treenode>::iterator it=s.lower_bound(ChthollyTree_Treenode(pos));
if(it!=s.end()&&it->l==pos)
{
return it;
}
--it;
int l=it->l,r=it->r,v=it->v;
s.erase(it);
s.insert(ChthollyTree_Treenode(l,pos-1,v));
return s.insert(ChthollyTree_Treenode(pos,r,v)).first;
}
void assign(int l,int r,int v)
{
set<ChthollyTree_Treenode>::iterator itr=split(r+1);
set<ChthollyTree_Treenode>::iterator itl=split(l);
s.erase(itl,itr);
s.insert(ChthollyTree_Treenode(l,r,v));
}
int querysum(int l,int r,int c)
{
int ans=0;
set<ChthollyTree_Treenode>::iterator itr=split(r+1);
set<ChthollyTree_Treenode>::iterator itl=split(l);
for(set<ChthollyTree_Treenode>::iterator it=itl;it!=itr;it++)
{
if(it->v==c)
{
ans+=(it->r-it->l+1);
}
}
return ans;
}
};
//FHQ_Treap(平衡树)
struct FHQ_Treap_node
{
int l,r,v,rnd,siz;
};
struct FHQ_Treap
{
vector<FHQ_Treap_node> t;
int cnt,rt;
FHQ_Treap(int n=0)
{
t.resize(n+6);
cnt=0;
rt=0;
}
inline int createnode(int x)
{
cnt++;
t[cnt].v=x;
t[cnt].rnd=rnd();
t[cnt].siz=1;
t[cnt].l=0;
t[cnt].r=0;
return cnt;
}
inline void pushup(int x)
{
t[x].siz=t[t[x].l].siz+t[t[x].r].siz+1;
}
inline void split(int x,int v,int &ls,int &rs)
{
if(x==0)
{
ls=rs=0;
return;
}
if(v>=t[x].v)
{
ls=x;
split(t[x].r,v,t[x].r,rs);
}
else
{
rs=x;
split(t[x].l,v,ls,t[x].l);
}
pushup(x);
}
inline int merge(int x,int y)
{
if(x==0||y==0)
{
return x+y;
}
if(t[x].rnd<t[y].rnd)
{
t[x].r=merge(t[x].r,y);
pushup(x);
return x;
}
t[y].l=merge(x,t[y].l);
pushup(y);
return y;
}
inline void insert(int v)
{
int x,y;
split(rt,v,x,y);
int pos=createnode(v);
rt=merge(merge(x,pos),y);
}
inline void del(int v)
{
int x,y,z;
split(rt,v,x,z);
split(x,v-1,x,y);
rt=merge(merge(x,merge(t[y].l,t[y].r)),z);
}
inline int queryrank(int v)
{
int x,y,ans=0;
split(rt,v-1,x,y);
ans=t[x].siz+1;
merge(x,y);
return ans;
}
inline int querynode(int pos,int k)
{
int siz=t[t[pos].l].siz;
if(k==siz+1)
{
return t[pos].v;
}
else if(k<=siz)
{
return querynode(t[pos].l,k);
}
else if(k>=siz)
{
return querynode(t[pos].r,k-siz-1);
}
}
inline int querypre(int v)
{
int x,y;
split(rt,v-1,x,y);
int ans=querynode(x,t[x].siz);
rt=merge(x,y);
return ans;
}
inline int querysuf(int v)
{
int x,y;
split(rt,v,x,y);
int ans=querynode(y,1);
rt=merge(x,y);
return ans;
}
};
//树状数组(区间查询,单点修改)
struct NormalBIT //支持区间查询,单点修改,默认加法
{
vector<int>c;
int n;
NormalBIT(int N=0)
{
n=N;
c.resize(N+6,0);
}
void update(int x,int y)
{
for(int i=x;i<=n;i+=lowbit(i))
{
c[i]+=y;
}
}
int query(int x)
{
int ans=0;
for(int i=x;i;i-=lowbit(i))
{
ans+=c[i];
}
return ans;
}
};
//普通线段树
struct NormalSegmentTree
{
vector<int>t,w,a;
NormalSegmentTree(int N=0)
{
t.resize(4*N+10);
w.resize(4*N+10);
a.resize(4*N+10);
}
void pushup(int u)
{
w[u]=w[u*2]+w[u*2+1];
}
void build(int l,int r,int x)
{
if(l==r)
{
w[x]=a[l];
return;
}
int mid=(l+r)/2;
build(l,mid,x*2);
build(mid+1,r,x*2+1);
pushup(x);
}
void maketag(int u,int s,int x)
{
t[u]+=x;
w[u]+=s*x;
}
void pushdown(int u,int l,int r)
{
int mid=(l+r)/2;
maketag(u*2,mid-l+1,t[u]);
maketag(u*2+1,r-mid,t[u]);
t[u]=0;
}
int query(int u,int x,int y,int l,int r)
{
if(l<=x&&y<=r)
{
return w[u];
}
else if(l>y||r<x)
{
return 0;
}
int mid=(x+y)/2;
pushdown(u,x,y);
return query(u*2,x,mid,l,r)+query(u*2+1,mid+1,y,l,r);
}
void update(int u,int x,int y,int l,int r,int k)
{
if(l<=x&&r>=y)
{
maketag(u,y-x+1,k);
return;
}
else if(l>y||r<x)
{
return;
}
int mid=(x+y)/2;
pushdown(u,x,y);
update(u*2,x,mid,l,r,k);
update(u*2+1,mid+1,y,l,r,k);
pushup(u);
}
};
//单调栈(最大最小值)
struct SimpleStack_Max
{
stack<int>s;
void clear()
{
while(!s.empty())
{
s.pop();
}
}
int top()
{
return s.top();
}
bool empty()
{
return s.empty();
}
void push(int x)
{
while(!s.empty()&&s.top()>x)
{
s.pop();
}
s.push(x);
}
};
struct SimpleStack_Min
{
stack<int>s;
void clear()
{
while(!s.empty())
{
s.pop();
}
}
int top()
{
return s.top();
}
bool empty()
{
return s.empty();
}
void push(int x)
{
while(!s.empty()&&s.top()<x)
{
s.pop();
}
s.push(x);
}
};
//ST表(最大、最小值)(注意:没有动态开空间!)
struct MaxnumSparseTable
{
int f[100005][30],a[100005],lg[100005];
void init(int n)
{
for(int i=1;i<=n;i++)
{
f[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i<=n-(1<<j)+1;i++)
{
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
}
}
for(int i=2;i<=n;i++)
{
lg[i]=lg[i>>1]+1;
}
}
int query(int l,int r)
{
int k=lg[r-l+1];
return max(f[l][k],f[r-(1<<k)+1][k]);
}
};
struct MinnumSparseTable
{
int f[100005][30],a[100005],lg[100005];
void init(int n)
{
for(int i=1;i<=n;i++)
{
f[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i<=n-(1<<j)+1;i++)
{
f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]);
}
}
for(int i=2;i<=n;i++)
{
lg[i]=lg[i>>1]+1;
}
}
int query(int l,int r)
{
int k=lg[r-l+1];
return min(f[l][k],f[r-(1<<k)+1][k]);
}
};
//并查集、扩展域并查集(2阶)
struct DSU
{
vector<int>f;
DSU(int N=0)
{
f.resize(N+5);
}
void init()
{
for(int i=0;i<f.size();i++)
{
f[i]=i;
}
}
void resize(int n)
{
f.resize(n+5);
}
int find(int x)
{
if(f[x]==x)
{
return x;
}
return f[x]=find(f[x]);
}
bool check(int x,int y)
{
return find(x)==find(y);
}
void merge(int x,int y)
{
f[find(x)]=find(y);
}
};
struct exareaDSU
{
vector<int>f;
int n;
exareaDSU(int N=0)
{
f.resize(2*N+5);
n=N;
}
void init()
{
for(int i=0;i<f.size();i++)
{
f[i]=i;
}
}
void resize(int N)
{
f.resize(2*N+5);
n=N;
}
int find(int x)
{
if(f[x]==x)
{
return x;
}
return f[x]=find(f[x]);
}
bool checkfriend(int x,int y)
{
return find(x)==find(y)||find(x+n)==find(y+n);
}
bool checkenmeny(int x,int y)
{
return find(x)==find(y+n)||find(y)==find(x+n);
}
void merge(int x,int y)
{
f[find(x)]=find(y);
}
void mergefriend(int x,int y)
{
merge(x,y);
merge(x+n,y+n);
}
void mergeenmeny(int x,int y)
{
merge(x+n,y);
merge(x,y+n);
}
};
}
//可持久化线段树
struct PersisdentSegmentTreeNode
{
int l,r,v;
};
struct PersisdentSegmentTree
{
vector<PersisdentSegmentTreeNode>t;
vector<int> a,rt;
int cnt=0;
void resize(int N)
{
t.resize((N<<5)+5);
a.resize(N+5);
rt.resize(N+5);
}
int create(int x)
{
cnt++;
t[cnt]=t[x];
return cnt;
}
int build(int x,int l,int r)
{
x=++cnt;
if(l==r)
{
t[x].v=a[l];
return cnt;
}
int mid=(l+r)/2;
t[x].l=build(t[x].l,l,mid);
t[x].r=build(t[x].r,mid+1,r);
return x;
}
int update(int x,int l,int r,int pos,int v)
{
x=create(x);
if(l==r)
{
t[x].v=v;
return x;
}
int mid=(l+r)/2;
if(pos<=mid)
{
t[x].l=update(t[x].l,l,mid,pos,v);
}
else
{
t[x].r=update(t[x].r,mid+1,r,pos,v);
}
return x;
}
int query(int x,int l,int r,int pos)
{
if(l==r)
{
return t[x].v;
}
int mid=(l+r)/2;
if(pos<=mid)
{
return query(t[x].l,l,mid,pos);
}
else
{
return query(t[x].r,mid+1,r,pos);
}
}
};
//-------------------------------------------------//
//-****************杂项********************//
//-------------------------------------------------//
namespace Matrix
{
struct Mat
{
#define int long long
double a[105][105];
int r,c;
Mat(int _r=0,int _c=0)
{
r=_r;
c=_c;
memset(a,0,sizeof(a));
if(c==0)
{
c=r;
}
}
void unit()
{
memset(a,0,sizeof(a));
for(int i=1;i<=r;i++)
{
a[i][i]=1;
}
}
Mat operator + (const Mat&t)const
{
Mat ans=*this;
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
ans.a[i][j]+=t.a[i][j];
}
}
return ans;
}
Mat operator - (const Mat&t)const
{
Mat ans=*this;
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
ans.a[i][j]-=t.a[i][j];
}
}
return ans;
}
Mat operator * (const Mat t)const
{
Mat ans(r,t.c);
int n=r,m=t.c;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=1;k<=c;k++)
{
ans.a[i][j]+=a[i][k]*t.a[k][j];
}
}
}
return ans;
}
void out()
{
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
printf("%.2lf ",a[i][j]);
}
printf("\n");
}
}
void input()
{
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
scanf("%lf",&a[i][j]);
}
}
}
Mat pow(ll b)
{
Mat ans(r);
Mat a=*this;
ans.unit();
while(b)
{
if(b&1)
{
ans=ans*a;
}
a=a*a;
b>>=1;
}
return ans;
}
#undef int
};
}
signed main()
{
}