NOIP ( CSP-S2 ) 复习范围(精简版)
给自己复习用的,作为弱省弱校选手能混到一等尾巴就满足了
数据结构
- 堆(priority_queue)
priority_queue <类型,vector<类型>,greater<类型> > q;//小顶堆
pair优先比较第一位
- 并查集
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=10010; 4 int n,m,f[maxn]; 5 int fi(int x){ 6 if(f[x]==x) 7 return x; 8 return f[x]=fi(f[x]); 9 } 10 int main(){ 11 scanf("%d%d",&n,&m); 12 for(int i=1;i<=n;i++)f[i]=i; 13 for(int i=1;i<=m;i++){ 14 int z,x,y; 15 scanf("%d%d%d",&z,&x,&y); 16 if(z==1){ 17 int fx=fi(x),fy=fi(y); 18 if(fx!=fy) 19 f[fx]=fy; 20 } 21 else{ 22 int fx=fi(x),fy=fi(y); 23 if(fx==fy) 24 printf("Y\n"); 25 else 26 printf("N\n"); 27 } 28 } 29 return 0; 30 }
- 树状数组
- 线段树
区间加+查询区间和:数组开四倍,懒标记每次下放一层
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn=100010; 5 int n,m; 6 ll tr[maxn*4],a[maxn],lzy[maxn*4]; 7 void build(int rt,int l,int r){ 8 if(l==r){ 9 tr[rt]=a[l]; 10 return; 11 } 12 int mid=(l+r)/2; 13 build(rt*2,l,mid); 14 build(rt*2+1,mid+1,r); 15 tr[rt]=tr[rt*2]+tr[rt*2+1]; 16 } 17 void pushdown(int rt,int l,int r){ 18 if(lzy[rt]){ 19 int mid=(l+r)/2; 20 tr[rt*2]+=lzy[rt]*(mid-l+1); 21 tr[rt*2+1]+=lzy[rt]*(r-mid); 22 lzy[rt*2]+=lzy[rt]; 23 lzy[rt*2+1]+=lzy[rt]; 24 lzy[rt]=0; 25 } 26 } 27 void add(int rt,int l,int r,int x,int y,ll k){ 28 if(x<=l&&r<=y){ 29 tr[rt]+=k*(r-l+1); 30 lzy[rt]+=k; 31 return; 32 } 33 pushdown(rt,l,r); 34 int mid=(l+r)/2; 35 if(x<=mid) 36 add(rt*2,l,mid,x,y,k); 37 if(y>mid) 38 add(rt*2+1,mid+1,r,x,y,k); 39 tr[rt]=tr[rt*2]+tr[rt*2+1]; 40 } 41 ll query(int rt,int l,int r,int x,int y){ 42 if(x<=l&&r<=y) 43 return tr[rt]; 44 pushdown(rt,l,r); 45 ll ans=0; 46 int mid=(l+r)/2; 47 if(x<=mid) 48 ans+=query(rt*2,l,mid,x,y); 49 if(y>mid) 50 ans+=query(rt*2+1,mid+1,r,x,y); 51 return ans; 52 } 53 int main(){ 54 scanf("%d%d",&n,&m); 55 for(int i=1;i<=n;i++) 56 scanf("%lld",&a[i]); 57 build(1,1,n); 58 while(m--){ 59 int opt; 60 scanf("%d",&opt); 61 if(opt==1){ 62 int x,y; 63 ll k; 64 scanf("%d%d%lld",&x,&y,&k); 65 add(1,1,n,x,y,k); 66 } 67 else{ 68 int x,y; 69 scanf("%d%d",&x,&y); 70 printf("%lld\n",query(1,1,n,x,y)); 71 } 72 } 73 return 0; 74 }
- ST表
- 单调队列
图论
- 最小生成树
- 最短路(Dijkstra+heap, floyd)
- 差分约束系统+负环判定+SPFA
形如a-b<=c的不等式集合,建从b到a长度为c的边;需超级源点,若有负环(某点入队次数>=n+1)则无解
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=50010,INF=0x3f3f3f3f; 4 struct edge{ 5 int nxt,v,w; 6 }e[maxn*2]; 7 int n,m,cnt,head[maxn],dis[maxn],vis[maxn],in[maxn]; 8 queue<int> q; 9 void addedge(int u,int v,int w){ 10 e[++cnt].nxt=head[u]; 11 e[cnt].v=v; 12 e[cnt].w=w; 13 head[u]=cnt; 14 } 15 bool spfa(){ 16 memset(dis,INF,sizeof(dis)); 17 dis[0]=0; 18 vis[0]=1; 19 q.push(0); 20 while(!q.empty()){ 21 int u=q.front(); 22 q.pop(); 23 vis[u]=0; 24 for(int i=head[u];i;i=e[i].nxt){ 25 int v=e[i].v,w=e[i].w; 26 if(dis[v]>dis[u]+w){ 27 dis[v]=dis[u]+w; 28 if(vis[v]==0){ 29 vis[v]=1; 30 q.push(v); 31 in[v]++; 32 if(in[v]>=n+1) 33 return false; 34 } 35 } 36 } 37 } 38 return true; 39 } 40 int main(){ 41 scanf("%d%d",&n,&m); 42 for(int i=1;i<=m;i++){ 43 int u,v,w; 44 scanf("%d%d%d",&u,&v,&w); 45 addedge(v,u,w); 46 } 47 for(int i=1;i<=n;i++) 48 addedge(0,i,0); 49 if(spfa()) 50 for(int i=1;i<=n;i++) 51 printf("%d ",dis[i]); 52 else 53 printf("NO"); 54 return 0; 55 }
- 拓扑排序
- 图的连通性问题(Tarjan三算法)
- 次短路和第K短路
- 二分图
- LCA
数论
- 欧几里得算法(拓展欧几里得算法)
- 埃氏筛
- 快速幂
- 中国剩余定理
- 乘法逆元
- 排列组合
动态规划
- 背包DP
- 线性DP
- 区间DP
- 树形DP
综合算法与思想
- 搜索(DFS, BFS, 记忆化)
- 贪心
- 高精
- 离线思想
- 倍增思想