[总结]板子整理QAQ
放些我比较喜欢的板子QAQ
SPFA最短路:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int N=2500+5; 9 const int M=6200+5; 10 int n,m; 11 struct edge{ 12 int from,to,dis; 13 }e[M<<1]; 14 int head[N],nxt[M<<1],tot=0; 15 void adde(int f,int t,int d) 16 { 17 e[++tot]=(edge){f,t,d}; 18 nxt[tot]=head[f]; 19 head[f]=tot; 20 } 21 int dist[N]; 22 bool inq[N]; 23 queue<int> q; 24 void spfa(int st) 25 { 26 dist[st]=0; 27 q.push(st); 28 inq[st]=1; 29 while(!q.empty()) 30 { 31 int u=q.front(); 32 q.pop(); 33 inq[u]=0; 34 for(int i=head[u];i;i=nxt[i]) 35 { 36 int v=e[i].to; 37 if(dist[v]>dist[u]+e[i].dis) 38 { 39 dist[v]=dist[u]+e[i].dis; 40 if(!inq[v]) 41 { 42 q.push(v); 43 inq[v]=1; 44 } 45 } 46 } 47 } 48 } 49 int main() 50 { 51 memset(dist,0x3f,sizeof(dist)); 52 int st,ed; 53 scanf("%d%d%d%d",&n,&m,&st,&ed); 54 int a,b,c; 55 for(int i=1;i<=m;i++) 56 { 57 scanf("%d%d%d",&a,&b,&c); 58 adde(a,b,c); 59 adde(b,a,c); 60 } 61 spfa(st); 62 printf("%d\n",dist[ed]); 63 return 0; 64 }
Dijkstra 最短路+堆优化
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int N=2500+5; 9 const int M=6200+5; 10 int n,m; 11 struct edge{ 12 int from,to,dis; 13 }e[M<<1]; 14 int head[N],nxt[M<<1],tot=0; 15 void adde(int f,int t,int d) 16 { 17 e[++tot]=(edge){f,t,d}; 18 nxt[tot]=head[f]; 19 head[f]=tot; 20 } 21 int dist[N]; 22 bool vis[N]; 23 struct zt{ 24 int id,dis; 25 bool operator <(const zt X) const{ 26 return X.dis<dis; 27 } 28 }; 29 priority_queue<zt> q; 30 void dij(int st) 31 { 32 dist[st]=0; 33 q.push((zt){st,0}); 34 while(!q.empty()) 35 { 36 int u=q.top().id; 37 q.pop(); 38 if(vis[u]) continue; 39 vis[u]=1; 40 for(int i=head[u];i;i=nxt[i]) 41 { 42 int v=e[i].to; 43 if(dist[v]>dist[u]+e[i].dis) 44 { 45 dist[v]=dist[u]+e[i].dis; 46 q.push((zt){v,dist[v]}); 47 } 48 } 49 } 50 } 51 int main() 52 { 53 memset(dist,0x3f,sizeof(dist)); 54 int st,ed; 55 scanf("%d%d%d%d",&n,&m,&st,&ed); 56 int a,b,c; 57 for(int i=1;i<=m;i++) 58 { 59 scanf("%d%d%d",&a,&b,&c); 60 adde(a,b,c); 61 adde(b,a,c); 62 } 63 dij(st); 64 printf("%d\n",dist[ed]); 65 return 0; 66 }
倍增版LCA,用于处理树上任意两点的距离
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int N=5e4+5; 9 int n,m; 10 struct edge{ 11 int from,to,dis; 12 }e[N<<1]; 13 int head[N],nxt[N<<1],tot=0; 14 void adde(int f,int t,int d) 15 { 16 e[++tot]=(edge){f,t,d}; 17 nxt[tot]=head[f]; 18 head[f]=tot; 19 } 20 int deep[N],anc[N][25],rank[N]; 21 void dfs(int t,int f) 22 { 23 deep[t]=deep[f]+1; 24 anc[t][0]=f; 25 for(int i=head[t];i;i=nxt[i]) 26 { 27 int v=e[i].to; 28 if(v!=f) 29 { 30 rank[v]=rank[t]+e[i].dis; 31 dfs(v,t); 32 } 33 } 34 } 35 void make_lca() 36 { 37 for(int j=1;j<=23;j++) 38 for(int i=1;i<=n;i++) 39 anc[i][j]=anc[anc[i][j-1]][j-1]; 40 } 41 int lca(int x,int y) 42 { 43 if(deep[x]<deep[y]) swap(x,y); 44 int dd=deep[x]-deep[y]; 45 for(int i=0;(1<<i)<=dd;i++) 46 { 47 if((1<<i)&dd) x=anc[x][i]; 48 } 49 if(x==y) return x; 50 for(int i=23;i>=0;i--) 51 { 52 if(anc[x][i]!=anc[y][i]) 53 x=anc[x][i],y=anc[y][i]; 54 } 55 return anc[x][0]; 56 } 57 58 int main() 59 { 60 scanf("%d",&n); 61 int a,b,c; 62 for(int i=1;i<=n-1;i++) 63 { 64 scanf("%d%d%d",&a,&b,&c); 65 a++,b++; 66 adde(a,b,c); 67 adde(b,a,c); 68 } 69 dfs(1,0); 70 make_lca(); 71 scanf("%d",&m); 72 while(m--) 73 { 74 scanf("%d%d",&a,&b); 75 a++,b++; 76 printf("%d\n",rank[a]+rank[b]-2*rank[lca(a,b)]); 77 } 78 return 0; 79 }
树剖版LCA,据说比倍增快
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int N=5e4+5; 9 int n,m; 10 struct edge{ 11 int from,to,dis; 12 }e[N<<1]; 13 int head[N],nxt[N<<1],tot=0; 14 void adde(int f,int t,int d) 15 { 16 e[++tot]=(edge){f,t,d}; 17 nxt[tot]=head[f]; 18 head[f]=tot; 19 } 20 int deep[N],fa[N],siz[N],hson[N],top[N],rank[N]; 21 void dfs1(int t,int f) 22 { 23 deep[t]=deep[f]+1; 24 fa[t]=f; 25 for(int i=head[t];i;i=nxt[i]) 26 { 27 int v=e[i].to; 28 if(v!=f) 29 { 30 rank[v]=rank[t]+e[i].dis; 31 dfs1(v,t); 32 siz[t]+=siz[v]; 33 if(!hson[t]||siz[v]>siz[hson[t]]) hson[t]=v; 34 } 35 } 36 } 37 void dfs2(int t,int tp) 38 { 39 top[t]=tp; 40 if(!hson[t]) return; 41 dfs2(hson[t],tp); 42 for(int i=head[t];i;i=nxt[i]) 43 { 44 int v=e[i].to; 45 if(v!=fa[t]&&v!=hson[t]) dfs2(v,v); 46 } 47 } 48 int lca(int x,int y) 49 { 50 int fx=top[x],fy=top[y]; 51 while(fx!=fy) 52 { 53 if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy); 54 x=fa[fx],fx=top[x]; 55 } 56 return deep[x]<deep[y]?x:y; 57 } 58 int main() 59 { 60 scanf("%d",&n); 61 int a,b,c; 62 for(int i=1;i<=n-1;i++) 63 { 64 scanf("%d%d%d",&a,&b,&c); 65 a++,b++; 66 adde(a,b,c); 67 adde(b,a,c); 68 } 69 scanf("%d",&m); 70 dfs1(1,0); 71 dfs2(1,1); 72 while(m--) 73 { 74 scanf("%d%d",&a,&b); 75 a++,b++; 76 printf("%d\n",rank[a]+rank[b]-2*rank[lca(a,b)]); 77 } 78 return 0; 79 }
线段树,用于区间搞事
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int maxn=2e5+5; 9 typedef long long ll; 10 int n,m; 11 ll num[maxn]; 12 struct seg{ 13 int l,r; 14 ll sum,add; 15 }tree[maxn<<2]; 16 inline void update(int p) 17 { 18 tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum; 19 } 20 void build(int p,int l,int r) 21 { 22 tree[p].l=l; 23 tree[p].r=r; 24 if(l==r) 25 { 26 tree[p].sum=num[l]; 27 return; 28 } 29 int mid=l+r>>1; 30 build(p<<1,l,mid); 31 build(p<<1|1,mid+1,r); 32 update(p); 33 } 34 void pushdown(int p) 35 { 36 if(tree[p].add) 37 { 38 ll v=tree[p].add; 39 int lz=p<<1,rz=p<<1|1; 40 tree[lz].add+=v; 41 tree[lz].sum+=v*(tree[lz].r-tree[lz].l+1); 42 tree[rz].add+=v; 43 tree[rz].sum+=v*(tree[rz].r-tree[rz].l+1); 44 tree[p].add=0; 45 } 46 } 47 void change(int p,int l,int r,ll v) 48 { 49 if(l<=tree[p].l&&r>=tree[p].r) 50 { 51 tree[p].add+=v; 52 tree[p].sum+=v*(tree[p].r-tree[p].l+1); 53 return; 54 } 55 pushdown(p); 56 int mid=tree[p].l+tree[p].r>>1; 57 if(l<=mid) change(p<<1,l,r,v); 58 if(r>mid) change(p<<1|1,l,r,v); 59 update(p); 60 } 61 ll ask_sum(int p,int l,int r) 62 { 63 if(l<=tree[p].l&&r>=tree[p].r) 64 { 65 return tree[p].sum; 66 } 67 pushdown(p); 68 int mid=tree[p].l+tree[p].r>>1; 69 ll ret=0; 70 if(l<=mid) ret+=ask_sum(p<<1,l,r); 71 if(r>mid) ret+=ask_sum(p<<1|1,l,r); 72 return ret; 73 } 74 int main() 75 { 76 scanf("%d",&n); 77 for(int i=1;i<=n;i++) 78 { 79 scanf("%lld",&num[i]); 80 } 81 build(1,1,n); 82 int op,a,b; 83 ll c; 84 scanf("%d",&m); 85 while(m--) 86 { 87 scanf("%d%d%d",&op,&a,&b); 88 if(op==1) 89 { 90 scanf("%lld",&c); 91 change(1,a,b,c); 92 } 93 else if(op==2) 94 { 95 printf("%lld\n",ask_sum(1,a,b)); 96 } 97 } 98 return 0; 99 }
树状数组,区间求和比较方便,代码简短
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int maxn=1e5+5; 9 #define lowbit(x) x&-x 10 int n,m; 11 int tree[maxn]; 12 void change(int pos,int v) 13 { 14 while(pos<=n) 15 { 16 tree[pos]+=v; 17 pos+=lowbit(pos); 18 } 19 } 20 int ask_sum(int l,int r) 21 { 22 if(l==1) 23 { 24 int ret=0; 25 while(r) 26 { 27 ret+=tree[r]; 28 r-=lowbit(r); 29 } 30 return ret; 31 } 32 return ask_sum(1,r)-ask_sum(1,l-1); 33 } 34 int main() 35 { 36 scanf("%d",&n); 37 int x; 38 for(int i=1;i<=n;i++) 39 { 40 scanf("%d",&x); 41 change(i,x); 42 } 43 scanf("%d",&m); 44 int op,a,b; 45 while(m--) 46 { 47 scanf("%d%d%d",&op,&a,&b); 48 if(op==1) change(a,b); 49 else if(op==2) printf("%d\n",ask_sum(a,b)); 50 } 51 return 0; 52 }
分块,和线段树、树状数组是一家子QAQ,代码优美,逼格较高
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int maxn=2e5+5; 9 const int sq=460+5; 10 typedef long long ll; 11 int n,m; 12 ll num[maxn]; 13 ll ksum[sq],kadd[sq]; 14 int inbl[maxn],kl; 15 void change(int l,int r,ll v) 16 { 17 if(inbl[l]==inbl[r]) 18 { 19 for(int i=l;i<=r;i++) num[i]+=v,ksum[inbl[i]]+=v; 20 return; 21 } 22 for(int i=l;inbl[i]==inbl[l];i++) num[i]+=v,ksum[inbl[i]]+=v; 23 for(int i=r;inbl[i]==inbl[r];i--) num[i]+=v,ksum[inbl[i]]+=v; 24 for(int i=inbl[l]+1;i<inbl[r];i++) kadd[i]+=v; 25 } 26 ll ask_sum(int l,int r) 27 { 28 ll ret=0; 29 if(inbl[l]==inbl[r]) 30 { 31 for(int i=l;i<=r;i++) ret+=num[i]+kadd[inbl[i]]; 32 return ret; 33 } 34 for(int i=l;inbl[i]==inbl[l];i++) ret+=num[i]+kadd[inbl[i]]; 35 for(int i=r;inbl[i]==inbl[r];i--) ret+=num[i]+kadd[inbl[i]]; 36 for(int i=inbl[l]+1;i<inbl[r];i++) ret+=ksum[i]+kadd[i]*kl; 37 return ret; 38 } 39 int main() 40 { 41 scanf("%d",&n); 42 kl=sqrt(n); 43 for(int i=1;i<=n;i++) 44 { 45 scanf("%lld",&num[i]); 46 inbl[i]=(i-1)/kl+1; 47 ksum[inbl[i]]+=num[i]; 48 } 49 scanf("%d",&m); 50 int op,a,b; 51 ll c; 52 while(m--) 53 { 54 scanf("%d%d%d",&op,&a,&b); 55 if(op==1) 56 { 57 scanf("%lld",&c); 58 change(a,b,c); 59 } 60 else if(op==2) 61 { 62 printf("%lld\n",ask_sum(a,b)); 63 } 64 } 65 return 0; 66 }
禁忌·树链剖分,支持树上两点间的搞事,代码极其长且难以调试,小白慎用
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int N=3e4+5; 9 int n,m; 10 int num[N]; 11 struct edge{ 12 int from,to; 13 }e[N<<1]; 14 int head[N],nxt[N<<1],tot=0; 15 void adde(int f,int t) 16 { 17 e[++tot]=(edge){f,t}; 18 nxt[tot]=head[f]; 19 head[f]=tot; 20 } 21 int deep[N],fa[N],siz[N],hson[N],top[N]; 22 int inseg[N],intr[N],ds=0; 23 void dfs1(int t,int f) 24 { 25 deep[t]=deep[f]+1; 26 fa[t]=f; 27 siz[t]=1; 28 for(int i=head[t];i;i=nxt[i]) 29 { 30 int v=e[i].to; 31 if(v!=f) 32 { 33 dfs1(v,t); 34 siz[t]+=siz[v]; 35 if(!hson[t]||siz[v]>siz[hson[t]]) hson[t]=v; 36 } 37 } 38 } 39 void dfs2(int t,int tp) 40 { 41 top[t]=tp; 42 inseg[t]=++ds; 43 intr[ds]=t; 44 if(!hson[t]) return; 45 dfs2(hson[t],tp); 46 for(int i=head[t];i;i=nxt[i]) 47 { 48 int v=e[i].to; 49 if(v!=fa[t]&&v!=hson[t]) dfs2(v,v); 50 } 51 } 52 struct seg{ 53 int l,r; 54 int sum,maxx; 55 }tree[N<<2]; 56 inline void update(int p) 57 { 58 tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum; 59 tree[p].maxx=max(tree[p<<1].maxx,tree[p<<1|1].maxx); 60 } 61 void build(int p,int l,int r) 62 { 63 tree[p].l=l; 64 tree[p].r=r; 65 if(l==r) 66 { 67 tree[p].sum=num[intr[l]]; 68 tree[p].maxx=num[intr[l]]; 69 return; 70 } 71 int mid=l+r>>1; 72 build(p<<1,l,mid); 73 build(p<<1|1,mid+1,r); 74 update(p); 75 } 76 void change(int p,int pos,int v) 77 { 78 if(tree[p].l==tree[p].r) 79 { 80 tree[p].sum=v; 81 tree[p].maxx=v; 82 return; 83 } 84 int mid=tree[p].l+tree[p].r>>1; 85 if(pos<=mid) change(p<<1,pos,v); 86 else change(p<<1|1,pos,v); 87 update(p); 88 } 89 int ask_sum(int p,int l,int r) 90 { 91 if(l<=tree[p].l&&r>=tree[p].r) 92 { 93 return tree[p].sum; 94 } 95 int mid=tree[p].l+tree[p].r>>1; 96 int ret=0; 97 if(l<=mid) ret+=ask_sum(p<<1,l,r); 98 if(r>mid) ret+=ask_sum(p<<1|1,l,r); 99 return ret; 100 } 101 int ask_maxx(int p,int l,int r) 102 { 103 if(l<=tree[p].l&&r>=tree[p].r) 104 { 105 return tree[p].maxx; 106 } 107 int mid=tree[p].l+tree[p].r>>1; 108 int ret=-2147483647; 109 if(l<=mid) ret=max(ret,ask_maxx(p<<1,l,r)); 110 if(r>mid) ret=max(ret,ask_maxx(p<<1|1,l,r)); 111 return ret; 112 } 113 int find_sum(int x,int y) 114 { 115 int fx=top[x],fy=top[y]; 116 int ret=0; 117 while(fx!=fy) 118 { 119 if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy); 120 ret+=ask_sum(1,inseg[fx],inseg[x]); 121 x=fa[fx],fx=top[x]; 122 } 123 if(deep[x]<deep[y]) swap(x,y); 124 ret+=ask_sum(1,inseg[y],inseg[x]); 125 return ret; 126 } 127 int find_maxx(int x,int y) 128 { 129 int fx=top[x],fy=top[y]; 130 int ret=-2147483647; 131 while(fx!=fy) 132 { 133 if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy); 134 ret=max(ret,ask_maxx(1,inseg[fx],inseg[x])); 135 x=fa[fx],fx=top[x]; 136 } 137 if(deep[x]<deep[y]) swap(x,y); 138 ret=max(ret,ask_maxx(1,inseg[y],inseg[x])); 139 return ret; 140 } 141 int main() 142 { 143 scanf("%d",&n); 144 int a,b; 145 for(int i=1;i<=n-1;i++) 146 { 147 scanf("%d%d",&a,&b); 148 adde(a,b); 149 adde(b,a); 150 } 151 dfs1(1,0); 152 dfs2(1,1); 153 for(int i=1;i<=n;i++) scanf("%d",&num[i]); 154 build(1,1,n); 155 scanf("%d",&m); 156 char op[10]; 157 while(m--) 158 { 159 scanf("%s%d%d",op,&a,&b); 160 if(op[1]=='S') printf("%d\n",find_sum(a,b)); 161 else if(op[1]=='M') printf("%d\n",find_maxx(a,b)); 162 else if(op[1]=='H') change(1,inseg[a],b); 163 } 164 return 0; 165 }
先整理这么多(不要跟我说LCT之类的,我不会啊QAQ)