当前位置: 首页 > news >正文

高级数据结构手册

LCA

//exam:P3379 【模板】最近公共祖先(LCA)
#include <iostream>
#include <cstdio>
#include <vector>
#define int long long 
using namespace std;
const int MAXN=5e5+5,MAXM=25;
void dfs(int,int);
int lca(int,int);
vector<int> g[MAXN];
int deep[MAXN];
int n,q,s;
signed main(){cin>>n>>q>>s;for(int i=1,u,v;i<n;i++){cin>>u>>v;g[u].push_back(v);g[v].push_back(u);}dfs(s,0);while(q--){int a,b;cin>>a>>b;cout<<lca(a,b)<<endl;}return 0;
} 
int f[MAXN][MAXM];
void dfs(int u,int fa){f[u][0]=fa,deep[u]=deep[fa]+1;for(int i=1;i<=20;i++){f[u][i]=f[f[u][i-1]][i-1];}for(int i=0;i<g[u].size();i++){int v=g[u][i];if(v!=fa){dfs(v,u);}}
}
int lca(int u,int v){if(deep[u]<deep[v]){swap(u,v);}int l=deep[u]-deep[v];for(int i=0;i<=20;i++){if(l&(1<<i)){u=f[u][i];} }if(u==v){return u;}for(int i=20;i>=0;i--){if(f[u][i]!=f[v][i]){u=f[u][i],v=f[v][i];}}return f[u][0];
}

树状数组

//exam:T588519 树状数组 3 :区间修改,区间查询
#include <iostream>
#include <cstdio>
#define int long long 
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int MAXN=1e6+5;
int query(int x);
void update(int x,int v);
int tree1[MAXN],tree2[MAXN];
int n,q;
signed main(){ios::sync_with_stdio(false);cin>>n>>q;for(int i=1,u;i<=n;i++){cin>>u;update(i,u);update(i+1,-u);}while(q--){int op,l,r,x;cin>>op>>l>>r;if(op==1){cin>>x;update(l,x);update(r+1,-x);}else{cout<<query(r)-query(l-1)<<endl;}}return 0;
} 
int query(int x){int res=0,res1=0,t=x;while(x){res+=tree1[x];res1+=tree2[x];x-=lowbit(x);}return res*(t+1)-res1;
}
void update(int x,int v){int v1=x*v;while(x<=n){tree1[x]+=v;tree2[x]+=v1;x+=lowbit(x);}
}

线段树

加法

//exam:P3372 【模板】线段树 1
#include <iostream>
#include <cstdio>
#define int long long 
using namespace std;
const int MAXN=1e5+5;
void build(int,int,int);
int query(int,int,int);
void update(int,int,int,int);
int a[MAXN];
int n,m;
signed main(){cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];}build(1,1,n);for(int i=1,op,x,y,k;i<=m;i++){cin>>op>>x>>y;if(op==1){cin>>k;update(1,x,y,k);} else{cout<<query(1,x,y)<<endl;}
//		for(int i=1;i<=n;i++){
//			cout<<query(1,i,i)<<" ";
//		}
//		cout<<endl;} return 0;
}
struct SegmentTree{int value,l,r,add;#define value(x) tree[x].value//节点权值 #define l(x) tree[x].l#define r(x) tree[x].r#define add(x) tree[x].add#define ltree(x) ((x)<<1)#define rtree(x) (((x)<<1)+1)#define treesize(x) (r(x)-l(x)+1)#define mid(x) ((l(x)+r(x))>>1)
}tree[MAXN*4];
void build(int root,int l,int r){l(root)=l,r(root)=r;if(l==r){value(root)=a[l];return ;}int mid=mid(root);build(ltree(root),l,mid);build(rtree(root),mid+1,r);value(root)=value(ltree(root))+value(rtree(root));return ;
}
void spread(int x){value(ltree(x))+=add(x)*treesize(ltree(x));value(rtree(x))+=add(x)*treesize(rtree(x));add(ltree(x))+=add(x);add(rtree(x))+=add(x);add(x)=0;
}
int query(int root,int l,int r){if(l<=l(root)&&r(root)<=r){return value(root);}spread(root);int mid=mid(root),res=0;if(mid>=l){res+=query(ltree(root),l,r);}if(mid<r){res+=query(rtree(root),l,r);}return res;
}
void update(int root,int l,int r,int x){if(l<=l(root)&&r(root)<=r){add(root)+=x;value(root)+=x*treesize(root);return ;}spread(root);int mid=mid(root);if(mid>=l){update(ltree(root),l,r,x);}if(mid<r){update(rtree(root),l,r,x);}value(root)=value(ltree(root))+value(rtree(root));
}

加法和乘法

//exam:P3373 【模板】线段树 2
#include <iostream>
#include <cstdio>
#define int long long 
using namespace std;
const int MAXN=1e5+5;
void build(int,int,int);
int query(int,int,int);
void update1(int,int,int,int);
void update2(int,int,int,int);
int a[MAXN];
int n,m,P;
signed main(){ios::sync_with_stdio(false);cin>>n>>m>>P;for(int i=1;i<=n;i++){cin>>a[i];}build(1,1,n);for(int i=1,op,x,y,k;i<=m;i++){cin>>op>>x>>y;if(op==1){cin>>k;update2(1,x,y,k);} else if(op==2){cin>>k;update1(1,x,y,k);} else{cout<<query(1,x,y)<<endl;}
//		cout<<"#";
//		for(int i=1;i<=n;i++){
//			cout<<query(1,i,i)<<" ";
//		}
//		cout<<endl;} return 0;
}
struct SegmentTree{int value,l,r,add,mul;#define value(x) tree[x].value//节点权值 #define l(x) tree[x].l#define r(x) tree[x].r#define add(x) tree[x].add#define mul(x) tree[x].mul#define ltree(x) ((x)<<1)#define rtree(x) (((x)<<1)+1)#define treesize(x) (r(x)-l(x)+1)#define mid(x) ((l(x)+r(x))>>1)
}tree[MAXN*4];
void build(int root,int l,int r){l(root)=l,r(root)=r,mul(root)=1;if(l==r){value(root)=a[l];return ;}int mid=mid(root);build(ltree(root),l,mid);build(rtree(root),mid+1,r);value(root)=value(ltree(root))+value(rtree(root));return ;
}
void spread(int x){value(ltree(x))=value(ltree(x))*mul(x)%P; value(rtree(x))=value(rtree(x))*mul(x)%P; value(ltree(x))=(value(ltree(x))+add(x)*treesize(ltree(x))%P)%P;value(rtree(x))=(value(rtree(x))+add(x)*treesize(rtree(x))%P)%P;add(ltree(x))=(add(ltree(x))*mul(x)%P+add(x))%P;add(rtree(x))=(add(rtree(x))*mul(x)%P+add(x))%P;mul(ltree(x))=mul(ltree(x))*mul(x)%P;mul(rtree(x))=mul(rtree(x))*mul(x)%P;add(x)=0,mul(x)=1;
}
int query(int root,int l,int r){if(l<=l(root)&&r(root)<=r){return value(root);}spread(root);int mid=mid(root),res=0;if(mid>=l){res=(res+query(ltree(root),l,r))%P;}if(mid<r){res=(res+query(rtree(root),l,r))%P;}return res;
}
void update1(int root,int l,int r,int x){if(l<=l(root)&&r(root)<=r){add(root)=(add(root)+x)%P;value(root)=(value(root)+x*treesize(root)%P)%P;return ;}spread(root);int mid=mid(root);if(mid>=l){update1(ltree(root),l,r,x);}if(mid<r){update1(rtree(root),l,r,x);}value(root)=(value(ltree(root))+value(rtree(root)))%P;
}
void update2(int root,int l,int r,int x){if(l<=l(root)&&r(root)<=r){add(root)=add(root)*x%P;mul(root)=mul(root)*x%P;value(root)=(value(root)*x%P)%P;return ;}spread(root);int mid=mid(root);if(mid>=l){update2(ltree(root),l,r,x);}if(mid<r){update2(rtree(root),l,r,x);}value(root)=(value(ltree(root))+value(rtree(root)))%P;
}

分块

//exam:243. 分块 
#include <algorithm>
#include <iostream>
#include <cstdio> 
#include <cmath>
#define int long long 
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=5e5+5;
void init();
int query(int,int,int);
void update(int,int,int);
pair<int,int> a[MAXN];
int n,m;
int T;
signed main(){ios::sync_with_stdio(false);cin>>n;for(int i=1;i<=n;i++){int t;cin>>t;a[i]=make_pair(t,i);}init();for(int i=1;i<=n;i++){int op,l,r,x;cin>>op>>l>>r>>x;if(op==1){cout<<query(l,r,x*x)<<endl;}else{update(l,r,x);}}return 0;
}
int pos[MAXN],L[MAXN],R[MAXN],add[MAXN];
void init(){T=sqrt(n);for(int i=1;i<=T;i++){L[i]=(i-1)*T+1,R[i]=i*T;}if(R[T]<n){L[T+1]=R[T]+1,R[T+1]=n;T++;}for(int i=1;i<=T;i++){sort(a+L[i],a+1+R[i]);for(int j=L[i];j<=R[i];j++){pos[j]=i;}}
}
int query(int x,int y,int k){int l=pos[x],r=pos[y],ans=0;if(l==r){for(int i=L[l];i<=R[l];i++){if(a[i].second>=x&&a[i].second<=y&&a[i].first<k-add[l]){ans++;}}}else{for(int i=L[l];i<=R[l];i++){if(a[i].second>=x&&a[i].first<k-add[l]){ans++;}}for(int i=l+1;i<=r-1;i++){ans+=lower_bound(a+L[i],a+R[i]+1,make_pair(k-add[i],-INF))-a-L[i];}for(int i=L[r];i<=R[r];i++){if(a[i].second<=y&&a[i].first<k-add[r]){ans++;}}}return ans;
}
void update(int x,int y,int k){int l=pos[x],r=pos[y];if(l==r){for(int i=L[l];i<=R[l];i++){if(a[i].second>=x&&a[i].second<=y){a[i].first+=k;}}sort(a+L[l],a+R[l]+1);}else{for(int i=L[l];i<=R[l];i++){if(a[i].second>=x){a[i].first+=k;}}sort(a+L[l],a+R[l]+1);for(int i=l+1;i<=r-1;i++){add[i]+=k;}for(int i=L[r];i<=R[r];i++){if(a[i].second<=y){a[i].first+=k;}}sort(a+L[r],a+R[r]+1);}
}

A*算法

//exam:P2901 [USACO08MAR] Cow Jogging G
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define int long long 
using namespace std;
struct node{int next,w;bool operator < (const node &nxt) const{if(w!=nxt.w){return w>nxt.w;}return next>nxt.next;}
};
const int MAXN=1005;
void build();//建立估算数组 
void output();
vector<node> g[MAXN],g0[MAXN];
priority_queue<node> q;
int d[MAXN];//估算数组 
int n,m,k;
signed main(){ios::sync_with_stdio(false);cin>>n>>m>>k;for(int i=1,u,v,w;i<=m;i++){cin>>u>>v>>w;g[u].push_back((node){v,w});g0[v].push_back((node){u,w});}build();q.push((node){n,d[n]});while(!q.empty()){node u=q.top();q.pop();
//		cout<<u.next<<" "<<u.w-d[u.next]<<" "<<u.w<<endl;if(u.next==1){cout<<u.w<<endl;k--;if(k==0){break;}}for(int i=0;i<g[u.next].size();i++){node v=g[u.next][i];q.push((node){v.next,d[v.next]+u.w-d[u.next]+v.w});}}while(k){cout<<-1<<endl;k--;}return 0;
}
void add(int v,int w){if(d[v]>=w){d[v]=w;q.push((node){v,w});}
}
void build(){for(int i=1;i<=n;i++){d[i]=0x3f3f3f3f;}add(1,0);while(!q.empty()){node u=q.top();q.pop();if(d[u.next]<u.w){continue;}for(int i=0;i<g0[u.next].size();i++){node v=g0[u.next][i];add(v.next,u.w+v.w);}}
}

最小生成树

//exam:P3366 【模板】最小生成树
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#define int long long 
using namespace std;
struct node{int v,w;
};
struct edge{int u,v,w;bool operator < (const edge &nxt) const{return w>nxt.w;}
};
const int MAXN=5e3+5;
int solve();
bool check();
priority_queue<edge> q;
vector<node> g[MAXN],a[MAXN];
int n,m,ans;
signed main(){ios::sync_with_stdio(false);cin>>n>>m;for(int i=1,u,v,w;i<=m;i++){cin>>u>>v>>w;g[u].push_back((node){v,w});g[v].push_back((node){u,w});q.push((edge){u,v,w});}ans=solve();if(!check()){cout<<"orz";}else{cout<<ans;}return 0; 
} 
bool book[MAXN];
void dfs(int cur){book[cur]=true;for(int i=0;i<a[cur].size();i++){node u=a[cur][i];if(!book[u.v]){dfs(u.v);}}
}
bool check(){dfs(1);for(int i=1;i<=n;i++){if(!book[i]){return false;}}return true;
}
int fa[MAXN];
void init(){for(int i=1;i<=n;i++){fa[i]=i;} 
}
int find(int x){if(fa[x]==x){return x; } return fa[x]=find(fa[x]);
}
void unity(int x,int y){int a=find(x),b=find(y);if(a==b){return ;} fa[a]=b;
} 
bool same(int x,int y){return find(x)==find(y);
}
int solve(){init();int ans=0;while(!q.empty()){edge u=q.top();q.pop();if(same(u.u,u.v)){continue;}unity(u.u,u.v);a[u.u].push_back((node){u.v,u.w});a[u.v].push_back((node){u.u,u.w});ans+=u.w;}return ans;
}

埃氏筛

//exam:P3383 【模板】线性筛素数
#include <iostream>
#include <cstdio>
#include <cmath>
//#define int long long
using namespace std;
const int MAXN=2e8+5;
bool book[MAXN];
int a[MAXN],b[MAXN];
int n,q,m;
signed main(){ios::sync_with_stdio(false);cin>>n>>q;for(int i=2;i<=n;i++){if(!book[i]){b[++m]=i;for(int j=i*2;j<=n;j+=i){book[j]=true;}}}for(int i=1;i<=q;i++){int x;cin>>x;cout<<b[x]<<endl;}return 0;
} 

线性筛

//exam:P3383 【模板】线性筛素数(线性筛)
#include <iostream>
#include <cstdio>
#include <cmath>
//#define int long long
using namespace std;
const int MAXN=2e8+5;
bool book[MAXN];
int a[MAXN],b[MAXN];
int n,q,m;
signed main(){ios::sync_with_stdio(false);cin>>n>>q;for(int i=2;i<=n;i++){if(!book[i]){b[++m]=i;}for(int j=1;j<=m&&i*b[j]<=n;j++){book[i*b[j]]=true;if(i%b[j]==0){break;}}}for(int i=1;i<=q;i++){int x;cin>>x;cout<<b[x]<<endl;}return 0;
} 

扩展欧几里得定理

//exam:P1082 [NOIP 2012 提高组] 同余方程
#include <iostream>
#include <cstdio>
#define int long long 
using namespace std;
void exgcd(int a,int b,int &x,int &y);
int a,b,x,y;
signed main(){ios::sync_with_stdio(false);cin>>a>>b;exgcd(a,b,x,y);cout<<x<<" "<<y;return 0;
}
void exgcd(int a,int b,int &x,int &y){if(b==0){x=1,y=0;return ;}exgcd(b,a%b,x,y);int x1=x,y1=y;x=y1,y=(x1-a/b*y1);
}

费马小定理&错排计数

//exam:P4071 [SDOI2016] 排列计数
#include <iostream>
#include <cstdio>
#define int long long 
#define endl '\n'
using namespace std;
const int P=1e9+7;
const int MAXN=1e6+5;
void build();
int solve(int,int);
int t,n,m;
signed main(){ios::sync_with_stdio(false);build();cin>>t;while(t--){cin>>n>>m;cout<<solve(n,m)<<endl;}return 0;
}
int f[MAXN],finv[MAXN],dp[MAXN];
int qpow(int x,int y){int res=1;while(y){if((y&1)==1){res=res*x%P;}y>>=1;x=x*x%P;}return res;
}
void build(){f[0]=finv[0]=1,dp[2]=1,dp[0]=1;for(int i=1;i<=1e6;i++){finv[i]=finv[i-1]*qpow(i,P-2)%P;//阶乘逆元f[i]=f[i-1]*i%P;if(i>=3){dp[i]=(i-1)*(dp[i-1]+dp[i-2])%P;}}
}
int C(int n,int m){return f[n]*finv[m]%P*finv[n-m]%P;
}
int solve(int n,int m){return C(n,m)*dp[n-m]%P;
}

字符串哈希

//exam:P10468 兔子与兔子
#include <iostream>
#include <cstdio>
#define int unsigned long long
using namespace std;
const int MAXN=1e6+5;
const int P=1331;
int hs(int,int);
string s;
int H[MAXN],PS[MAXN];
int n,x1,x2,y1,y2;
signed main(){ios::sync_with_stdio(false);cin>>s>>n;s=" "+s;PS[0]=1;for(int i=1;i<s.size();i++){H[i]=H[i-1]*P+s[i];PS[i]=PS[i-1]*P;}while(n--){cin>>x1>>y1>>x2>>y2;int h1=hs(x1,y1),h2=hs(x2,y2);if(h1==h2){cout<<"Yes\n";}else{cout<<"No\n";}}return 0;
}
int hs(int l,int r){return H[r]-H[l-1]*PS[r-l+1];
}

Trie

//exam:P10470 前缀统计
#include <iostream>
#include <cstring>
#include <cstdio>
#define int long long
#define endl '\n' 
using namespace std;
const int MAXN=1e6+5;
const int MAXM=30;
struct trie{#define idx(c) ((c)-'a')int ch[MAXN][MAXM];//ch[i][j]表示节点,j表示边int val[MAXN];//记录当前节点的信息 int size;//节点数量 trie(){//构造函数 size=0;memset(ch[0],0,sizeof(ch[0]));}void insert(string s){int u=0;for(int i=0;i<s.size();i++){int t=idx(s[i]);if(ch[u][t]==0){size++;memset(ch[size],0,sizeof(ch[size]));ch[u][t]=size;}u=ch[u][t];}val[u]++;}int query(string s){int u=0,res=val[0];for(int i=0;i<s.size();i++){int t=idx(s[i]);if(ch[u][t]==0){break;}u=ch[u][t];res+=val[u];}return res;}
};
int n,m;
trie t;
signed main(){ios::sync_with_stdio(false);cin>>n>>m;for(int i=1;i<=n;i++){string s;cin>>s;t.insert(s);}for(int i=1;i<=m;i++){string s;cin>>s;cout<<t.query(s)<<endl;}return 0;
}

KMP

//exam:P3375 【模板】KMP
#include <iostream>
#include <cstdio>
#define int long long 
using namespace std;
const int MAXN=1e6+5;
void getF(string);
int fail[MAXN];//失配 
string s1,s2;
int cur;
signed main(){ios::sync_with_stdio(false);cin>>s2>>s1;//模式串,匹配串 getF(s1);for(int i=0;i<s2.size();i++){if(s1[cur]==s2[i]){cur++;}else{while(cur&&s2[i]!=s1[cur]){cur=fail[cur];}cur=(s2[i]==s1[cur]?(cur+1):0);}if(cur==s1.size()){cout<<i-s1.size()+2<<endl; cur=fail[cur];}}for(int i=1;i<=s1.size();i++){cout<<fail[i]<<" ";}return 0;
}
void getF(string s){fail[0]=fail[1]=0;int l=s.size();for(int i=1;i<l;i++){//从i状态算i+1 int cur=fail[i];//失配之后到达的状态while(cur&&s[cur]!=s[i]){//不断失配 cur=fail[cur];} fail[i+1]=(s[cur]==s[i]?(cur+1):0);}
}
http://www.hskmm.com/?act=detail&tid=10265

相关文章:

  • Tarjan 学习笔记
  • 使用JavaScript和CSS创建动态高亮导航栏
  • Gridspech 全通关
  • 1967
  • 20253320蒋丰任
  • .
  • 又有两位智驾大牛联手入局具身智能机器人赛道创业,已完成数亿元融资!
  • 纯国产GPU性能对比,谁才是国产算力之王?
  • 地平线明年发布并争取量产舱驾一体芯片;比亚迪补强智舱团队,斑马智行原 CTO 加入
  • 英伟达入股英特尔,当竞争对手便成协作者,真正受益的......
  • ODT/珂朵莉树 入门
  • 在AI技术快速实现功能的时代,挖掘新需求成为关键突破点——某知名游戏资源分析工具需求洞察
  • 蜜罐
  • 【光照】[漫反射]UnityURP兰伯特有光照衰减吗?
  • prenotami.esteri.it 意大利签证预约error
  • reLeetCode 热题 100- 15. 三数之和 - MKT
  • XXL-TOOL v2.1.0 发布 | Java工具类库
  • Python-Pathlib库
  • 反省
  • [Nacos/Docker/MCP] Nacos 3.x : 为 AI MCP 而生
  • 牛客周赛 Round 108 CDEF题解
  • Redis的使用问题
  • AIGC拾遗:Flash Attention
  • 深度好文-风雨飘摇信竞路
  • Python-CSV库
  • C++小白修仙记_LeetCode刷题_位运算
  • C++小白修仙记_LeetCode刷题_双指针
  • 前路漫漫亦灿灿 往事堪堪亦澜澜
  • 使用uv和pycharm搭建python开发环境
  • lc1032-字符流