NOIP复赛知识点复习:算法/数据结构模板
2017-10-17 13:04
309 查看
如有错误请及时指出~
(纯手打,持续更新中……)目录:
编号 | 算法/数据结构 |
---|---|
0 | 对拍程序 |
1 | 邻接表 |
2 | LCA |
3 | SPFA |
4 | 线性筛 |
5 | 快速幂 |
6 | 读入优化 |
7 | 二分(求上/下界) |
8 | 并查集 |
9 | 线段树 |
10 | 二分图匹配 |
11 | 网络流 |
12 | 树状数组 |
0.对拍程序
转自http://blog.csdn.net/wlx65003/article/details/51149196
@echo off :loop rand.exe > in.txt my.exe < in.txt > myout.txt std.exe < in.txt > stdout.txt fc myout.txt stdout.txt if not errorlevel 1 goto loop pause goto loop
1.邻接表
难度:2
有很多种写法,强烈安利我的这种写法,操作简单、便捷。
#include<cstdio> #include<algorithm> #include<cstring> #define maxn 100050 #define add(u,v,vv) to[++top]=head[u],head[u]=top,w[top]=v,val[top]=vv #define For(x) for(int h=head[x],o=w[h],v=val[h];h;o=w[h=to[h]],v=val[h]) using namespace std; int n,m,i,top=0,head[maxn*2],to[maxn*2],w[maxn*2],val[maxn*2],u,v,vv; int main() { scanf("%d%d",&n,&m); for (i=1;i<=m;i++) scanf("%d%d%d",&u,&v,&vv),add(u,v,vv); for (i=1;i<=n;i++) For(i) printf("%d to %d:%d\n",i,o,v); }
2.LCA(最近公共祖先)
难度:2.5
#include<cstdio> #include<algorithm> #include<cstring> #define maxn 100050 #define add(u,v) to[++top]=head[u],head[u]=top,w[top]=v #define For(x) for(int h=head[x],o=w[h];h;o=w[h=to[h]]) using namespace std; int n,q,u,v,i,top=0,f[maxn][25],d[maxn],head[maxn*2],to[maxn*2],w[maxn*2]; inline void dfs(int x,int fa) { d[x]=d[fa]+1; for (i=1;i<=20;i++) f[x][i]=f[f[x][i-1]][i-1]; For(x) if (o!=fa) f[o][0]=x,dfs(o,x); } inline int lca(int u,int v) { if (d[u]<d[v]) swap(u,v); for (int i=20;i>=0;i--) { if (d[f[u][i]]>=d[v]) 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]; } int main() { scanf("%d%d",&n,&q); for (i=1;i<n;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u); dfs(1,0); while (q--) scanf("%d%d",&u,&v),printf("%d",lca(u,v)); }
3.SPFA
难度:3
队列优化的bfs,时间复杂度O(km)(k约等于2)。
#include<cstdio> #include<algorithm> #include<cstring> #define maxn 100050 #define add(u,v,vv) to[++top]=head[u],head[u]=top,w[top]=v,val[top]=vv #define For(x) for(int h=head[x],o=w[h],v=val[h];h;o=w[h=to[h]],v=val[h]) using namespace std; int top=0,l,r,q[maxn*2],dis[maxn],bo[maxn],head[maxn],to[maxn],w[maxn],val[maxn],n,m,u,v,vv,s,t,x; inline void spfa() { q[l=r=0]=s,memset(bo,0,sizeof(bo)),memset(dis,0x7f,sizeof(dis)),dis[s]=0,bo[s]=1; while (l<=r) { x=q[l]; For(x) if (dis[x]+v<dis[o]) { dis[o]=dis[x]+v; if (!bo[o]) bo[o]=1,q[++r]=o; } l++,bo[x]=0; } } int main() { scanf("%d%d",&n,&m); while (m--) scanf("%d%d%d",&u,&v,&vv),add(u,v,vv); scanf("%d%d",&s,&t),spfa(),printf("%d",dis[t]); }
4.线性筛
难度:2.5
时间复杂度仅为O(n)。
#include<cstdio> #include<algorithm> #include<cstring> #define maxn 10000050 using namespace std; int f[maxn],p[maxn],top=0,i,j,n; int main() { scanf("%d",&n),f[0]=f[1]=1,p[0]=0; for (i=2;i<=n;i++) { if (f[i]==0) p[++top]=i; for (j=1;j<=top&&i*p[j]<=n;j++) { f[i*p[j]]=1; if (i%p[j]==0) break; } } printf("%d\n",top); for (i=1;i<=top;i++) printf("%d ",p[i]); }
5.快速幂
难度:2.5
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; ll x,y,m; ll qsm(ll x,ll y,ll m) { ll ret=1; x%=m; while (y) { if (y&1) ret*=x; ret%=m,x*=x,x%=m,y/=2; } return ret; } int main() { scanf("%lld%lld%lld",&x,&y,&m),printf("%lld",qsm(x,y,m)); }
6.读入优化
难度:2,必备技巧
inline void read(int &x) { x=0; int f=1; char ch=getchar(); while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); } while (isdigit(ch)) { x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } x*=f; }
7.二分
难度:2
推荐两个函数:lower_bound&upper_bound(具体用法不再解释)
对于线性递增的数组,x值的位置下界为lower_bound(a+1,a+n+1,x)-a,上界为upper_bound(a+1,a+n+1,x)-a-1;
求下界:
void binary_find() { l=1,r=INF; while (l!=r) { int mid=(l+r)/2; if (check(mid)) r=mid;else l=mid+1; } }
求上界:(注意细节)
void binary_find() { l=1,r=INF; while (l!=r) { int mid=(l+r+1)/2; if (check(mid)) l=mid;else r=mid-1; } }
8.并查集
不带权的版本,难度:2
#include<cstdio> #include<algorithm> #include<cstring> #define maxn 10050 using namespace std; int f[maxn],n,m,u,v,opt; inline int find(int x) { if (x==f[x]) return x; f[x]=find(f[x]); return f[x]; } inline void union_(int u,int v) {f[find(u)]=find(v);} int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) f[i]=i; while (m--) { scanf("%d%d%d",&opt,&u,&v); if (opt==1) union_(u,v); else if (find(u)==find(v)) printf("Y\n");else printf("N\n"); } }
9.线段树(区间加/乘,求和模板)
难度:4
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define maxn 100050 using namespace std; typedef long long ll; int a[maxn],ql,qr,val,opt,n,m,p; struct segment_tree { ll t[maxn*4],lz1[maxn*4],lz2[maxn*4]; inline void pushup(int x) {t[x]=t[x*2]+t[x*2+1];} inline void pushdown(int x,int l,int r) { if (lz1[x]==1&&lz2[x]==0) return; if (lz1[x]!=1) { lz1[x*2]=(lz1[x]*lz1[x*2])%p; lz1[x*2+1]=(lz1[x]*lz1[x*2+1])%p; lz2[x*2]=(lz1[x]*lz2[x*2])%p; lz2[x*2+1]=(lz1[x]*lz2[x*2+1])%p; t[x*2]=(t[x*2]*lz1[x])%p; t[x*2+1]=(t[x*2+1]*lz1[x])%p; lz1[x]=1; } int mid=(l+r)/2; if (lz2[x]!=0) { lz2[x*2]=(lz2[x*2]+lz2[x])%p; lz2[x*2+1]=(lz2[x*2+1]+lz2[x])%p; t[x*2]=(t[x*2]+(mid-l+1)*lz2[x])%p; t[x*2+1]=(t[x*2+1]+(r-mid)*lz2[x])%p; lz2[x]=0; } } inline void build(int x,int l,int r) { if (l==r) {t[x]=a[l],lz1[x]=1;return;} int mid=(l+r)/2; build(x*2,l,mid),build(x*2+1,mid+1,r),pushup(x),lz1[x]=1; } inline void upd(int x,int l,int r,int ql,int qr,int val,int k) //k=1:* k=2:+ { if (l==ql&&r==qr) { if (k==1) lz1[x]=(lz1[x]*val)%p,lz2[x]=(lz2[x]*val)%p,t[x]=(t[x]*val)%p; if (k==2) lz2[x]=lz2[x]+val,t[x]=(t[x]+val*(r-l+1))%p; return; } pushdown(x,l,r); int mid=(l+r)/2; if (qr<=mid) upd(x*2,l,mid,ql,qr,val,k); else if (ql>mid) upd(x*2+1,mid+1,r,ql,qr,val,k); else upd(x*2,l,mid,ql,mid,val,k),upd(x*2+1,mid+1,r,mid+1,qr,val,k); pushup(x); } inline ll query(int x,int l,int r,int ql,int qr) { if (l==ql&&r==qr) {return t[x]%p;} pushdown(x,l,r),pushup(x); int mid=(l+r)/2; if (qr<=mid) return query(x*2,l,mid,ql,qr)%p; else if (ql>mid) return query(x*2+1,mid+1,r,ql,qr)%p; else return (query(x*2,l,mid,ql,mid)+query(x*2+1,mid+1,r,mid+1,qr))%p; } }s; inline void rd(int &x) { x=0; char ch=getchar(); while (!isdigit(ch)) ch=getchar(); while (isdigit(ch)) x=(x<<3)+(x<<1)+ch-48,ch=getchar(); } int main() { rd(n),rd(m),rd(p); for (int i=1;i<=n;i++) rd(a[i]); s.build(1,1,n); while (m--) { rd(opt); if (opt==1) rd(ql),rd(qr),rd(val),s.upd(1,1,n,ql,qr,val,1); if (opt==2) rd(ql),rd(qr),rd(val),s.upd(1,1,n,ql,qr,val,2); if (opt==3) rd(ql),rd(qr),printf("%lld\n",s.query(1,1,n,ql,qr)); } }
10。二分图匹配
难度:3.5
#include<cstdio> #include<algorithm> #include<cstring> #define add(u,v) to[++top]=head[u],head[u]=top,w[top]=v #define For(x) for(int h=head[x],o=w[h];h;o=w[h=to[h]]) #define maxn 5050 using namespace std; int top=0,to[maxn*maxn],head[maxn*maxn],w[maxn*maxn],t[maxn],vis[maxn],ans=0,n,m,e,u,v; inline bool dfs(int x) { For(x) if (!vis[o]) { vis[o]=1; if (!t[o]||dfs(o)) {t[o]=x; return 1;} } return 0; } int main() { scanf("%d%d%d",&n,&m,&e); while (e--) { scanf("%d%d",&u,&v); if (u<=n&&v<=m) add(u,v); } for (int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if (dfs(i)) ans++; } printf("%d",ans); }
11.网络流
难度:4
#include<cstdio> #include<algorithm> #include<cstring> #define maxn 10050 #define maxm 100050 #define INF 1000000000 #define add(u,v,vv) to[++top]=head[u],head[u]=top,w[top]=v,cap[top]=vv #define For(x) for(int h=head[x],o=w[h];h;o=w[h=to[h]]) using namespace std; int top=1,to[maxm*2],head[maxm*2],w[maxm*2],cap[maxm*2],level[maxn],q[maxn*8],l,r,s,t,x; int n,m,u,v,vv; inline bool bfs() { memset(level,0,sizeof(level)); q[l=r=0]=s,level[s]=1; while (l<=r) { x=q[l++]; For(x) if (cap[h]&&level[o]==0) level[o]=level[x]+1,q[++r]=o; } return level[t]; } inline int dfs(int x,int maxflow) { if (x==t||!maxflow) return maxflow; int ret=0; For(x) if (cap[h]&&level[o]==level[x]+1) { int tmp=dfs(o,min(cap[h],maxflow)); ret+=tmp,maxflow-=tmp,cap[h]-=tmp,cap[h^1]+=tmp; } if (!ret) level[x]=0; return ret; } inline int dinic() { int ret=0; while (bfs()) ret+=dfs(s,INF); return ret; } int main() { scanf("%d%d%d%d",&n,&m,&s,&t); for (int i=1;i<=m;i++) scanf("%d%d%d",&u,&v,&vv),add(u,v,vv),add(v,u,0); printf("%d",dinic()); }
12.树状数组
难度:3
我不会同时区间加/求和~
单点加/区间求和:(l到r和为query(r)-query(l-1))
区间加/单点询问:(l到r加x:add(l,x),add(r+1,-x))
inline void add(int x,int y) {while (x<=n) t[x]+=y,x+=lowbit(x);} inline int query(int x) { int ret=0; while (x>=1) ret+=t[x],x-=lowbit(x); return ret; }
相关文章推荐
- NOIP复赛复习(六)算法分析与排序模板
- NOIP复赛复习(六)算法分析与排序模板
- NOIP复赛复习(八)STL算法与树结构模板
- NOIP复赛复习(七)STL容器与字符串模板
- NOIP复赛复习(十四)字符串算法巩固与提高
- NOIP复赛复习(五)程序对拍与图论模板
- NOIP复赛复习(十二)数论算法巩固与提高
- NOIP复赛复习(三)文件读写与数论模板
- NOIP复赛复习(十一)基础算法巩固与提高
- NOIP复赛复习(十四)字符串算法巩固与提高
- NOIP复赛复习(七)STL容器与字符串模板
- 冲刺NOIP复习,算法知识点总结
- [NOIP 2014复习]第四章:高效算法与高效数据结构
- NOIP复赛复习(三)文件读写与数论模板
- NOIP复赛复习(四)读写外挂与高精度模板
- NOIP复赛复习(十一)基础算法巩固与提高
- NOIP复赛复习(五)程序对拍与图论模板
- NOIP复赛复习(十二)数论算法巩固与提高
- 数据结构和算法的基本知识点复习
- 【总结】NOIP复赛来袭,各种算法经验大杂烩