并查集
定义 & 初始化
| int fa[N]; |
| void uInit() |
| { |
| for(int i=1;i<=n;i++) |
| fa[i]=i; |
| return; |
| } |
查询
| int uask(int x) |
| { |
| if(fa[x]==x) return fa[x]; |
| else return fa[x]=uask(fa[x]); |
| } |
合并
| void merge(int x,int y) |
| { |
| fa[ask(y)]=ask(x); |
| return; |
| } |
压行版本
| int ufa[N]; |
| void uInit(){iota(ufa+1,ufa+n+1,1);return;} |
| int uask(int x){return ufa[x]==x?x:ufa[x]=uask(ufa[x]);} |
| void umerge(int x,int y){ufa[uask(y)]=uask(x);return;} |
单调队列
| head=1,tail=0; |
| for(int i=1;i<=n;i++) |
| { |
| while(head<=tail && i-q[head]+1>k) q[head++]=0; |
| while(head<=tail && a[q[tail]]>a[i]) q[tail--]=0; |
| q[++tail]=i; |
| if(i>=k) res[i-k+1]=q[head]; |
| } |
单调栈
| for(int i=n;i>=1;i--) |
| { |
| while(top && a[sta[top]]<=a[i]) |
| sta[top--]=0; |
| ans[i]=sta[top]; |
| sta[++top]=i; |
| } |
链表
定义
| struct Peter{ |
| int val; |
| int nxt,pre; |
| }node[M]; |
| int idx=0; |
初始化
| inline void Init() |
| { |
| node[0]={0,n+1,0}; |
| node[n+1]={0,n+1,0}; |
| return; |
| } |
在 p
后插入 val
| inline void insert(int p,int val) |
| { |
| node[++idx]={val,node[p].nxt,p}; |
| node[node[p].nxt].pre=idx,node[p].nxt=idx; |
| return; |
| } |
删除 p
| inline void remove(int p) |
| { |
| node[node[p].nxt].pre=node[p].pre; |
| node[node[p].pre].nxt=node[p].nxt; |
| return; |
| } |
ST 表
\(f_{i,j}\) 表示 \(a_i \sim a_{i+2^j-1}\) 的最大值。
| namespace ST_Table{ |
| |
| void Init() |
| { |
| for(int i=2;i<=n;i++) |
| lg2[i]=lg2[i>>1]+1; |
| for(int k=1;k<=lg2[n];i++) |
| for(int i=1;i+(1<<k)-1<=n;i++) |
| f[i][k]=max(f[i][k-1],f[i+(1<<k-1)][k-1]); |
| return; |
| } |
| inline int Query(int l,int r) |
| { |
| int p=lg2[r-l+1]; |
| return max(f[l][p],f[r-(1<<p)+1][p]); |
| } |
| |
| } |
树状数组
| int lowbit(int x){return x&-x;} |
| void add(int x,int y) |
| { |
| for(;x<=n;x+=lowbit(x)) |
| c[x]+=y; |
| return; |
| } |
| int query(int x) |
| { |
| int res=0; |
| for(;x;x-=lowbit(x)) |
| res+=c[x]; |
| return res; |
| } |
线段树
单点修改
| namespace SegmentTree{ |
| |
| struct SegmentTree{ |
| int l,r; |
| int dat; |
| int get_mid(){return l+r>>1;} |
| }tree[N<<2]; |
| void update(int p) |
| { |
| tree[p].dat=tree[p<<1].dat+tree[p<<1|1].dat; |
| return; |
| } |
| void Build(int l,int r,int p=1) |
| { |
| tree[p].l=l,tree[p].r=r; |
| if(l==r) |
| { |
| treee[p].dat=a[l]; |
| return; |
| } |
| int mid=tree[p].get_mid(); |
| Build(l,mid,p<<1),Build(mid+1,r,p<<1|1); |
| update(p); |
| return; |
| } |
| void add(int x,int y,int p=1) |
| { |
| if(tree[p].l==tree[p].r) |
| { |
| tree[p].dat+=y; |
| return; |
| } |
| int mid=tree[p].get_mid(); |
| if(x<=mid) Add(x,y,p<<1); |
| else Add(x,y,p<<1|1); |
| update(p); |
| return; |
| } |
| int query(int l,int r,int p=1) |
| { |
| if(l<=tree[p].l&&tree[p].r<=r) return tree[p].dat; |
| int mid=tree[p].get_mid(),res=0; |
| if(l<=mid) res+=query(l,r,p<<1); |
| if(r>mid) res+=query(l,r,p<<1|1); |
| return res; |
| } |
| |
| } |
区间修改(延迟标记)
| namespace SegmentTree{ |
| |
| struct SegmentTree{ |
| int l,r; |
| int dat,lazy; |
| int get_mid(){return l+r>>1;} |
| int get_len(){return r-l+1;} |
| }tree[N<<2]; |
| void update(int p) |
| { |
| tree[p].dat=tree[p<<1].dat+tree[p<<1|1].dat; |
| return; |
| } |
| void spread(int p) |
| { |
| if(tree[p].lazy) |
| { |
| tree[p<<1].dat+=tree[p].lazy*tree[p<<1].get_len(); |
| tree[p<<1|1].dat+=tree[p].lazy*tree[p<<1|1].get_len(); |
| tree[p<<1].lazy+=tree[p].lazy; |
| tree[p<<1|1].lazy+=tree[p].lazy; |
| tree[p].lazy=0; |
| } |
| return; |
| } |
| void Build(int l,int r,int p=1) |
| { |
| tree[p].l=l,tree[p].r=r; |
| if(l==r) |
| { |
| treee[p].dat=a[l]; |
| return; |
| } |
| int mid=tree[p].get_mid(); |
| Build(l,mid,p<<1),Build(mid+1,r,p<<1|1); |
| update(p); |
| return; |
| } |
| void add(int l,int r,int x,int p=1) |
| { |
| if(l<=tree[p].l&&tree[p].r<=r) |
| { |
| tree[p].dat+=x*tree[p].get_len(); |
| tree[p].lazy+=x; |
| return; |
| } |
| spread(p) |
| int mid=tree[p].get_mid(); |
| if(l<=mid) add(l,r,x,p<<1); |
| if(r>mid) add(l,r,x,p<<1|1); |
| update(p); |
| return; |
| } |
| int query(int l,int r,int p=1) |
| { |
| if(l<=tree[p].l&&tree[p].r<=r) return tree[p].dat; |
| spread(p); |
| int mid=tree[p].get_mid(),res=0; |
| if(l<=mid) res+=query(l,r,p<<1); |
| if(r>mid) res+=query(l,r,p<<1|1); |
| return res; |
| } |
| |
| } |
平衡树
有旋 Treap
| namespace TREAP{ |
| |
| const int INF=1e18; |
| struct Treap{ |
| int ls,rs; |
| int val,dat; |
| int cnt,sz; |
| }tree[M+N]; |
| #define ls(p) tree[p].ls |
| #define rs(p) tree[p].rs |
| int root,idx; |
| |
| mt19937 engine(chrono::steady_clock::now().time_since_epoch().count()); |
| inline int create(int val) |
| { |
| tree[++idx]={0,0,val,(int)engine(),1,1}; |
| return idx; |
| } |
| inline void update(int p) |
| { |
| tree[p].sz=tree[ls(p)].sz+tree[rs(p)].sz+tree[p].cnt; |
| return; |
| } |
| inline void zig(int &p) |
| { |
| int q=ls(p); |
| tree[p].ls=rs(q); |
| tree[q].rs=p; |
| p=q; |
| update(rs(p)),update(p); |
| return; |
| } |
| inline void zag(int &p) |
| { |
| int q=rs(p); |
| tree[p].rs=ls(q); |
| tree[q].ls=p; |
| p=q; |
| update(ls(p)),update(p); |
| return; |
| } |
| |
| inline void Build() |
| { |
| root=create(-INF); |
| tree[root].rs=create(INF); |
| tree[rs(root)].dat=tree[root].dat-1; |
| update(root); |
| return; |
| } |
| |
| int get_rank(int val,int p) |
| { |
| if(!p) return 1; |
| if(val==tree[p].val) return tree[ls(p)].sz+1; |
| if(val<tree[p].val) return get_rank(val,ls(p)); |
| if(val>tree[p].val) return get_rank(val,rs(p))+tree[ls(p)].sz+tree[p].cnt; |
| return -INF; |
| } |
| int get_value(int rank,int p) |
| { |
| if(!p) return INF; |
| if(rank<=tree[ls(p)].sz) return get_value(rank,ls(p)); |
| else if(rank<=tree[ls(p)].sz+tree[p].cnt) return tree[p].val; |
| else return get_value(rank-tree[ls(p)].sz-tree[p].cnt,rs(p)); |
| } |
| |
| void Insert(int val,int &p) |
| { |
| if(!p) {p=create(val); return;} |
| if(val==tree[p].val) |
| { |
| tree[p].cnt++; |
| update(p); |
| return; |
| } |
| if(val<tree[p].val) |
| { |
| Insert(val,ls(p)); |
| if(tree[p].dat<tree[ls(p)].dat) zig(p); |
| } |
| if(val>tree[p].val) |
| { |
| Insert(val,rs(p)); |
| if(tree[p].dat<tree[rs(p)].dat) zag(p); |
| } |
| update(p); |
| return; |
| } |
| void Remove(int val,int &p) |
| { |
| if(!p) return; |
| if(val==tree[p].val) |
| { |
| if(tree[p].cnt>1) |
| { |
| tree[p].cnt--; |
| update(p); |
| return; |
| } |
| else if(ls(p)||rs(p)) |
| { |
| if(!rs(p) || tree[ls(p)].dat>tree[rs(p)].dat) |
| zig(p), Remove(val,rs(p)); |
| else zag(p), Remove(val,ls(p)); |
| update(p); |
| } |
| else p=0; |
| return; |
| } |
| if(val<tree[p].val) Remove(val,ls(p)); |
| if(val>tree[p].val) Remove(val,rs(p)); |
| update(p); |
| return; |
| } |
| |
| int get_prev(int val) |
| { |
| int res=0,p=root; |
| while(p) |
| { |
| if(val==tree[p].val) |
| { |
| if(ls(p)>0) |
| { |
| p=ls(p); |
| while(rs(p)>0) p=rs(p); |
| res=p; |
| } |
| break; |
| } |
| if(tree[p].val<val && (tree[p].val>tree[res].val || !res)) res=p; |
| p=val<tree[p].val?ls(p):rs(p); |
| } |
| return tree[res].val; |
| } |
| int get_next(int val) |
| { |
| int res=0,p=root; |
| while(p) |
| { |
| if(val==tree[p].val) |
| { |
| if(rs(p)) |
| { |
| p=rs(p); |
| while(ls(p)) p=ls(p); |
| res=p; |
| } |
| break; |
| } |
| if(tree[p].val>val && (tree[p].val<tree[res].val || !res)) res=p; |
| p=val<tree[p].val?ls(p):rs(p); |
| } |
| return tree[res].val; |
| } |
| |
| } |
无旋 Treap(FHQ Treap / FHQ 平衡树)
| namespace FHQ{ |
| |
| struct Treap{ |
| int ls,rs; |
| int val,dat; |
| int sz; |
| }tree[N+M]; |
| int idx,root; |
| #define ls(p) tree[p].ls |
| #define rs(p) tree[p].rs |
| |
| mt19937 engine(chrono::steady_clock::now().time_since_epoch().count()); |
| inline int create(int val) |
| { |
| tree[++idx]={0,0,val,(int)engine(),1}; |
| return idx; |
| } |
| inline void update(int p) |
| { |
| tree[p].sz=tree[ls(p)].sz+tree[rs(p)].sz+1; |
| return; |
| } |
| |
| void Split(int val,int p,int &L,int &R) |
| { |
| if(!p) {L=R=0; return;} |
| if(tree[p].val<=val) |
| { |
| L=p; |
| Split(val,rs(p),rs(p),R); |
| update(L); |
| } |
| else |
| { |
| R=p; |
| Split(val,ls(p),L,ls(p)); |
| update(R); |
| } |
| return; |
| } |
| int Merge(int L,int R) |
| { |
| if(!L||!R) return L+R; |
| if(tree[L].dat>tree[R].dat) |
| { |
| rs(L)=Merge(rs(L),R); |
| update(L); |
| return L; |
| } |
| else |
| { |
| ls(R)=Merge(L,ls(R)); |
| update(R); |
| return R; |
| } |
| return 0; |
| } |
| |
| void Insert(int val) |
| { |
| int p=create(val); |
| int L,R; Split(val,root,L,R); |
| root=Merge(L,Merge(p,R)); |
| return; |
| } |
| void Remove(int val) |
| { |
| int NR,R; Split(val,root,NR,R); |
| int L,MID; Split(val-1,NR,L,MID); |
| MID=Merge(ls(MID),rs(MID)); |
| root=Merge(L,Merge(MID,R)); |
| return; |
| } |
| |
| int get_rank(int val) |
| { |
| int L,R; Split(val-1,root,L,R); |
| int res=tree[L].sz+1; |
| root=Merge(L,R); |
| return res; |
| } |
| int get_value(int rank) |
| { |
| int p=root; |
| while(p) |
| { |
| int lsz=tree[ls(p)].sz; |
| if(rank==lsz+1) return tree[p].val; |
| if(rank<=lsz) p=ls(p); |
| else rank-=lsz+1,p=rs(p); |
| } |
| return -1; |
| } |
| |
| int get_prev(int val) |
| { |
| return get_value(get_rank(val)-1); |
| } |
| int get_next(int val) |
| { |
| return get_value(get_rank(val+1)); |
| } |
| |
| } |
笛卡尔树
建树
| for(int i=1;i<=n;i++) |
| { |
| scanf("%d",&a[i]); |
| while(top && a[sta[top]]>a[i]) |
| sta[top--]=0; |
| ls[i]=rs[sta[top]]; |
| rs[sta[top]]=i; |
| sta[++top]=i; |
| } |
线性基
贪心法
| const int B=60; |
| struct Basis{ |
| long long b[B+5]; |
| Basis(){memset(b,0,sizeof(b));} |
| void insert(long long x) |
| { |
| for(int i=B;i>=0;i--) |
| if((x>>i)&1) |
| { |
| if(b[i]) x^=b[i]; |
| else {b[i]=x;break;} |
| } |
| return; |
| } |
| long long getmax() |
| { |
| long long res=0; |
| for(int i=B;i>=0;i--) |
| res=max(res,res^b[i]); |
| return res; |
| } |
| }; |
高斯消元
| int bidx; |
| void bInit() |
| { |
| bidx=1; |
| #define getbin(x,pos) (((x)>>(pos))&1) |
| for(int i=B;i>=0;i--) |
| { |
| int p=bidx; |
| while(p<=n && !getbin(a[p],i)) p++; |
| if(p>n) continue; |
| swap(a[p],a[bidx]); |
| for(int j=1;j<=n;j++) |
| if(j!=bidx && getbin(a[j],i)) |
| a[j]^=a[bidx]; |
| bidx++; |
| } |
| #undef getbin |
| return; |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话