NOIP复赛模板及技巧积累(不定期更新)
来源:互联网 发布:软件基础架构平台 编辑:程序博客网 时间:2024/06/03 22:50
一.对拍
新建 1.bat,然后编辑
:loopdate.exepro.execheck.exefc pro.out check.outif %errorlevel%==0 goto loop
二.考试须知
1.内存(小心开炸,爆零)
若使用了结构体
可在主函数中:
printf("%lf\n",sizeof(P30)/1024.0/1024);
2.两数相乘(炸int)
3.取模(题目看仔细)
4.long long(注意数据范围)
5.文件名(复制)
6.读入输出(查看读入输出文件名)
7.输出调试(一定得关掉)
三.造数据
1.造树
srand(time(NULL)); int n; cin>>n; for(int i=0;i<n;i++)A[i]=i+1; for(int i=1;i<=1e6;i++){ swap(A[rand()%n],A[rand()%n]); } for(int i=1;i<=n;i++)printf("%d %d\n",A[rand()%i],A[i]);
注意:rand()大约只有3万多
四.日常加速
1.读入挂
void Rd(int &res){ res=0;char c; while(c=getchar(),c<48); do res=(res<<3)+(res<<1)+(c&15); while(c=getchar(),c>=48);}
建议不要读负数
2.正向表
适用于图论中代替vector
int nxt[M<<1],head[M],To[M],V[M],ttaE;void addedge(int a,int b,int c){ nxt[++ttaE]=a;head[a]=ttaE; To[tta]=b;V[tta]=c;}
3.手打堆
五.图论
1.迪杰斯特拉
如果加上手打堆会超快
struct node{ int v,id; bool operator<(const node &s)const{ return v>s.v; }};priority_queue<node>q;void dij(int x){ memset(dis,0,sizeof(dis)); dis[x]=0; q.push((node){0,x}); while(!q.empty()){ node now=q.top();q.pop(); if(dis[now.id]<now.v)continue; LFOR(i,x){ int y=To[i]; int v=V[i]; if(dis[y]==-1||dis[y]>dis[x]+v){ dis[y]=dis[x]+v; q.push((node){dis[y],y}); } } }}
2.SPFA
实现较为轻松,一般情况跑得较快,但复杂度玄学,可能被卡成n*m
void spfa(int x){ memset(dis,-1,sizeof(dis)); memset(mark,0,sizeof mark); mark[x]=1; queue<int>q; q.push(x); while(!q.empty()){ int now=q.front();q.pop(); mark[now]=0; LFOR(i,x){ int nxt=To[i]; if(dis[nxt]>dis[now]+V[i]||dis[nxt]==-1){ dis[nxt]=dis[now]+V[i]; if(!mark[nxt]){ q.push(nxt); mark[nxt]=1; } } } }}
3.Bell_man
可判负环
void relax(int u,int v,int w){ if(dis[u]>dis[v]+w)dis[u]=dos[v]+w;}void bellman(){ for(int i=1;i<n;i++){ for(int j=1;j<=m;j++){ relax(edge[j].x,edge[j].y,edge[j].v); } } //判负环 bool flag=0; for(int i=1;i<=m;i++){ if(dis[edge[i].x]>dis[edge[i].y]+edge[i].v){flag=1;break;} } return flag;}
4.floyd
水分利器,再次强调三层for的顺序
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) chk_mi(dis[i][j],dis[i][k]+dis[k][j]);
5.最小生成树
这里只介绍kruskal算法 因为它快而且简单啊
struct EDGE{ int v,x,y; bool operator <(const EDGE &_){ return v<_.v; }}edge[M];int fa[M];int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}int kruskal{ int ans=0; sort(edge+1,edge+m+1); for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=m;i++){ int a=find(edge[i].x),b=find(edge[i].y); if(a!=b){ ans+=edge[i].v; fa[a]=b; } } return ans;}
6.LCA(倍增)
实现容易,比树链剖分慢一些
void dfs(int x,int f){ fa[0][x]=f;dep[x]=dep[f]+1; LFOR(i,x){ int y=To[i]; if(y==f)continue; dfs(y,x); }}void init(){ for(int i=1;i<S;i++) for(int j=1;j<=n;j++) fa[i][x]=fa[i-1][fa[i-1][x]];}void Up(int &x,int len){ for(int i=0;i<S;i++)if(len&(1<<i))x=fa[i][x];}int LCA(int x,int y){ if(dep[x]>dep[y])swap(x,y); Up(y,dep[y]-dep[x]); if(x==y)return x; for(int i=S-1;i>=0;i--){ if(fa[i][x]!=fa[i][y]){ x=fa[i][x]; y=fa[i][y]; } } return fa[0][x];}
7.LCA(树链剖分)
听说均摊复杂度比tarjan【O(1)】还快 orz;
#include<bits/stdc++.h>using namespace std;int sz[M],son[M],fa[M],Top[M],dep[M];void ldfs(int x,int f){ sz[x]=1,son[x]=-1; fa[x]=f,dep[x]=dep[f]+1; LFOR(i,x){ int y=To[i]; if(y==f)continue; ldfs(y,x); sz[x]+=sz[y]; if(!~son[x]&&sz[son[x]]<sz[y])son[x]=y; }}void rdfs(int x,int tp){ Top[x]=tp; if(!~son[x])return; rdfs(son[x],tp); LFOR(i,x){ int y=To[i]; if(y==son[x]||y==fa[x])continue; rdfs(y,y); }}int LCA(int x,int y){ while(Top[x]!=Top[y]){ if(dep[Top[x]]>dep[Top[y]])x=fa[Top[x]]; else y=fa[Top[y]]; } return dep[x]<dep[y]?x:y;}
六.数论
1.gcd
图轮只会打模板
贪心只能过样例
dp打表找规律
数论只会gcd
void gcd(int x,int y){return !x?y:gcd(y,x%y);}
2.ex_gcd
主要套了gcd的壳
这样可以算出一组解,然后满足x=x0+kb y=y0-ka;
当满足b==0是x=0,y=1;然后 y=y-x*(a/b);
void exgcd(int a,int b,int &c,int &x,int &y){ if(!b){c=a,x=1,y=0;return;} else exgcd(b,a%b,c,y,x);y-=x*(a/b);}
3.快速幂
ll fast(ll x,ll n,ll P){ ll res=1; while(n){ if(n&1)res=res*x%P; n=n>>1; x=x*x%P; } return res;}
4.组合数
1.递推
for(int i=1;i<=n;i++){ C[i][0]=C[i][i]=1; for(int j=1;j<i;j++)C[i][j]=C[i-1][j]+C[i-1][j-1];}
2.逆元
O(nlogn)求以n为底的组合数
C[0]=1; for(int i=1;i<=n;i++)C[i]=C[i-1]*(n-i+1)%P*fast(i,P-2)%P;
3.线性求逆元
复杂度为O(n)
B[1]=1; FOR(i,2,n)B[i]=1LL*(Mod-Mod/i)*B[Mod%i]%Mod;
5.埃氏筛法
void init(){ for(int i=2;i<=n;i++){ if(mark[i])continue; for(int j=i+i;j<=n;j+=i)mark[j]=1; }}
七.数据结构
1.线段树
(以区间最值为例子)
1.单点更新,区间查询
struct Segment_Tree{ #define Lson l,mid,p<<1 #define Rson mid+1,r,p<<1|1 struct node{int l,r,mx;}tree[M<<2];//a为延时标记 void up(int p){ tree[p].mx=max(tree[p<<1].mx,tree[p<<1|1].mx); } void build(int l,int r,int p){ tree[p].l=l,tree[p].r=r; if(l==r){ tree[p].mx=A[l]; return; } int mid=(l+r)>>1; build(Lson);build(Rson); up(p); } void update(int pos,int x,int p){ if(tree[p].l==l&&tree[p].r==r){ tree[p].mx=x; return; } int mid=(tree[p].l+tree[p].r)>>1; if(mid>=pos)update(pos,x,p<<1); else update(pos,x,p<<1|1); up(p); } int query(int l,int r,int p){ if(tree[p].l==l&&tree[p].r==r){ return tree[p].mx; } int mid=(tree[p].l+tree[p].r)>>1; if(mid>=r)return query(l,r,p<<1); else if(mid<l)return query(l,r,p<<1|1); else return max(query(Lson),query(Rson)); }}Tree;
2.区间更新,单点查询
struct Segment_Tree{ #define Lson l,mid,p<<1 #define Rson mid+1,r,p<<1|1 struct node{int l,r,mx;}tree[M<<2];//a为延时标记 void up(int p){ tree[p].mx=max(tree[p<<1].mx,tree[p<<1|1].mx); } void build(int l,int r,int p){ tree[p].l=l,tree[p].r=r; if(l==r){ tree[p].mx=A[l]; return; } int mid=(l+r)>>1; build(Lson);build(Rson); up(p); } void update(int l,int r,int x,int p){ if(tree[p].l==l&&tree[p].r==r){ tree[p].mx=x; return; } int mid=(tree[p].l+tree[p].r)>>1; if(mid>=r)update(l,r,x,p<<1); else if(mid<l)update(l,r,x,p<<1|1); else update(l,mid,x,p<<1),update(mid+1,r,x,p<<1|1); up(p); } int query(int pos,int p){ if(tree[p].l==tree[p].r){ return tree[p].mx; } int mid=(tree[p].l+tree[p].r)>>1; if(mid>=pos)return max(tree[p].mx,query(pos,p<<1)); else return max(tree[p].mx,query(pos,p<<1|1)); }}Tree;
3.区间更新,区间查询
struct Segment_Tree{ #define Lson l,mid,p<<1 #define Rson mid+1,r,p<<1|1 struct node{int l,r,mx,a;}tree[M<<2];//a为延时标记 void up(int p){ tree[p].mx=max(tree[p<<1].mx,tree[p<<1|1].mx); } void down(int p){ if(!tree[p].a)return; tree[p<<1].a=tree[p].a,tree[p<<1|1].a=tree[p].a; tree[p<<1].mx=tree[p].mx,tree[p<<1|1].mx=mx; tree[p].a=0; } void build(int l,int r,int p){ tree[p].l=l,tree[p].r=r,tree[p].a=0; if(l==r){ tree[p].mx=A[l]; return; } int mid=(l+r)>>1; build(Lson);build(Rson); up(p); } void update(int l,int r,int x,int p){ if(tree[p].l==l&&tree[p].r==r){ tree[p].mx=x; tree[p].a=1; return; } down(p); int mid=(tree[p].l+tree[p].r)>>1; if(mid>=r)update(l,r,x,p<<1); else if(mid<l)update(l,r,x,p<<1|1); else update(l,mid,x,p<<1),update(mid+1,r,p<<1|1); up(p); } int query(int l,int r,int p){ if(tree[p].l==l&&tree[p].r==r){ return tree[p].mx; } down(p); int mid=(tree[p].l+tree[p].r)>>1; if(mid>=r)return query(l,r,p<<1); else if(mid<l)return query(l,r,p<<1|1); else return max(query(Lson),query(Rson)); }}Tree;
2.BIT
主题思想是前缀和
空间复杂度和时间复杂度还有代码长度都是线段树的四分之一
struct BIT{ #define lowbit(x) x&-x int Sum[M] void update(int x,int a){ while(x<=n){ Sum[x]+=a; x+=lowbit(x); } } int query(int x){ int res=0; while(x){ res+=Sum[x]; x-=lowbit(x); } return res; }}Bit;
3.并查集
void init(int n){for(int i=1;i<=n;i++)fa[i]=i;}int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}void unite(int x,int y){fa[find(x)]=find(y);}bool same(int x,int y){return find(x)==find(y);}
4.高精度
已经过性能测试,可能还存在什么小bug
大部分的功 能都有
#include<bits/stdc++.h>using namespace std;struct Bignum{ int A[1005],len; static const int P=10000; Bignum(){memset(A,0,sizeof A);len=1;} void Rd(){ char C[1005]; scanf("%s",C+1); int n=strlen(C+1); len=0; for(int i=n;i>=1;i-=4){ len++; A[len]=0; for(int j=max(1,i-3);j<=i;j++){ A[len]=(A[len]<<3)+(A[len]<<1)+(C[j]&15); } } while(len>1&&!A[len])len--; } Bignum operator +(const Bignum &S)const{ Bignum tmp; tmp.len=max(S.len,len); for(int i=1;i<=tmp.len;i++){ tmp.A[i]+=A[i]+S.A[i]; if(tmp.A[i]>=P){ tmp.A[i]-=P; tmp.A[i+1]++; } } if(tmp.A[tmp.len+1])tmp.len++; return tmp; } Bignum operator *(const Bignum &S)const{ Bignum tmp; tmp.len=S.len+len-1; for(int i=1;i<=len;i++){ for(int j=1;j<=S.len;j++){ tmp.A[i+j-1]+=A[i]*S.A[j]; tmp.A[i+j]+=tmp.A[i+j-1]/P; tmp.A[i+j-1]=tmp.A[i+j-1]%P; } } if(tmp.A[tmp.len+1])tmp.len++; while(!tmp.A[tmp.len]&&tmp.len>1)tmp.len--; return tmp; } Bignum operator -(const Bignum &S)const{ Bignum tmp; tmp.len=max(S.len,len); for(int i=tmp.len;i>=1;i--){ tmp.A[i]+=A[i]-S.A[i]; if(tmp.A[i]<0){ tmp.A[i]+=P; tmp.A[i+1]--; } } while(!tmp.A[tmp.len])tmp.len--; return tmp; } bool operator <(const Bignum &S)const{ if(S.len!=len)return len<S.len; for(int i=len;i>=1;i--){ if(A[i]!=S.A[i])return A[i]<S.A[i]; } return 0; } bool operator ==(const Bignum &S)const{ if(len!=S.len)return 0; for(int i=1;i<=len;i++){ if(A[i]!=S.A[i])return 0; } return 1; } bool operator <=(const Bignum &S)const{ return *this<S||*this==S; } Bignum operator /(const int &p)const{ Bignum tmp=*this; for(int i=len;i>=1;i--){ if(i>1)tmp.A[i-1]+=tmp.A[i]%p*P; tmp.A[i]=tmp.A[i]/p; } while(tmp.len>1&&!tmp.A[tmp.len])tmp.len--; return tmp; } Bignum operator +(const int &p)const{ Bignum tmp; tmp=*this; tmp.A[1]+=p; int now=1; while(tmp.A[now]>=P){ tmp.A[now+1]++; tmp.A[now]-=P; now++; } if(tmp.A[tmp.len+1])tmp.len++; return tmp; } Bignum operator -(const int &p)const{ Bignum tmp; tmp=*this; tmp.A[1]-=p; int now=1; while(tmp.A[now]<0){ tmp.A[now+1]--; tmp.A[now]+=P; now++; } if(!tmp.A[tmp.len]&&tmp.len>1)tmp.len--; return tmp; } Bignum operator /(const Bignum &S)const{ Bignum l,r,res; if(*this<S)return res; r=*this; while(l<=r){ Bignum mid=(l+r)/2; if((mid*S)<=*this){ res=mid; l=mid+1; } else r=mid-1; } return res; } void print(){ printf("%d",A[len]); for(int i=len-1;i>0;i--)printf("%04d",A[i]);puts(""); }}a,b,c;int main(){ a.Rd(),b.Rd(); c=a/b; c.print(); return 0;}
八.排序
1.归并排序
2.快速排序
3.堆排序
9.错误小结
1.与系统变量冲突
(25126)全局变量y1,y0
(25081)全局函数名hash
(24221)全局函数名begin
(24198)全局数组名rank
(23836)全局数组名next
(21994)全局数组名log2
(19969)全局数组名less
(19960)全局数组名ws
(18453)全局数组名prev
(15807)全局数组名pow
(13017)全局数组名time
(11360)全局数组名end
(9924)全局数组名index
(12213)全局数组名cos
- NOIP复赛模板及技巧积累(不定期更新)
- 算法核心思想总结及模板(不定期更新)
- 消息使用的积累(不定期更新)
- Perl 工作积累(不定期更新)
- TensorFlow及深度学习相关资料积累汇总【不定期更新】
- NOIP复赛的各种模板
- 字符串问题 ---模板(不定期更新中。)
- stl库积累(不定期更新
- linux 操作技巧整理(不定期更新)
- 分享技巧-工具(不定期更新)
- VIM实用小技巧(不定期更新)
- android优化小技巧(不定期更新)
- Sql自用技巧(不定期更新)
- Excel使用技巧(不定期更新)
- NOIP提高组常用姿势(不定期更新)
- 渗透技巧不定期更新
- NOIP复赛复习(七)STL容器与字符串模板
- NOIP复赛复习(六)算法分析与排序模板
- 人生永远没有太晚的开始
- C++动态申请二维数组
- 简易Web服务器
- hibernate持久化对象的四个状态
- 关于技术和产品的一些体会
- NOIP复赛模板及技巧积累(不定期更新)
- 【排序算法大合集】
- 查看CDH各组件版本
- 西瓜书《机器学习》课后答案——chapter5
- 次小生成树的学习 POJ1679 The Unique MST
- palindrome-partitioning-ii
- Java双链表增删改查基本操作
- 1012. 数字分类 (20)
- 数据结构笔试、面试