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, 记忆化)
  • 贪心
  • 高精
  • 离线思想
  • 倍增思想

 

posted @ 2020-10-26 20:31  yelvsu  阅读(172)  评论(0)    收藏  举报