当前位置:   article > 正文

考研复试 - 机试模板_考研计算机机试材料

考研计算机机试材料

去年开始不让携带纸质资料了,整理一些模板来背一下。

因为没有划定考察范围,时间有限只准备熟悉的,网络流,扩展kmp之类比较难的就不准备了。主要参考《算法笔记》、《明月册》的内容。

机房里只提供Dev C++, 用了一下很难用,一个是没有代码单词提示(输入prin不会提示printf),一个是不知道万能头让不让用,还要背一下头文件。

考前必看

  • 仔细看输入输出要求,写完代码对照一下,尤其是特殊情况。

比如:如果无法到达,输出 “WTF”。

这里光计算最短时间就很繁琐,最后终于写好了之后,很可能忘掉不可能的情况,所以最后输出要

特别注意一下output里的条件。

  • 所有提交的代码,提交前必须先自己试几组数据:①最小的情况, ②最大的情况 。③正常的情况。
  • 是否需要开long long

  • 数组是否开小,n<=150的开数组开a[155]

  • 1e5以上的数据读入用scanf而不用cin

第0章. C++头文件

  1. #include <stdio.h> // 标准io, printf和scanf和getchar
  2. #include <iostream> // c++io, cin和cout
  3. #include <algorithm> // STL中的sort,__gcd()等一些常用函数
  4. #include <string>  // STL中的string
  5. #include <string.h>  // c普通的字符串,memset()函数
  6. #include <vector> // STL中的vector
  7. #include <set>
  8. #include <map>
  9. #include <queue> // STL中的priority_queue和queue
  10. #include <stack>
  11. #include <cmath>  // acos(), log(), sin()等
  12. #include <stdlib.h> // rand()函数
 

第一章 - 入门知识点

1.3 二分

题目中,要求输出一个整数答案,满足最大值最小,或最小值最大。

把二分当作一个工具来使用,不是代码的全部。 重点是check函数

  1. int main() {
  2.    int left=0, right=100000000;
  3.    while ( left<=right ) {
  4.        int mid = (left+right)/2;
  5.        if ( check(mid)==1 ) {
  6.            ans = mid;
  7.            right = mid-1;
  8.       }
  9.        else left = mid + 1;
  10.   }
  11.    cout << ans << endl;
  12.    
  13.    return 0;
  14. }

1.5 差分

[ L , R ] 区间都+5, 只需要 arr[ L ] += 5, arr[ R+1 ] -=5; 最后for循环一遍arr,定义一个变量now一边更新加上去。

题意:n个灯刚开始是关的,m次操作对【L,R】内的全部的灯反转。问最后有几个灯亮着。

思路:刚开始差分直接便利了所有点,T了。所有只需要考虑哪些有贡献的2*m个点就行了,对于区间中哪些0的部分,就不需要遍历了。对于重复的点也不用管。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int n,m,cnt;
  4. struct node {
  5.    int id,x;
  6. }a[3005];
  7. int rule( node a, node b )
  8. {
  9.    return a.id<b.id;
  10. }
  11. int main() {
  12.    cin>>n>>m;
  13.    while ( m-- ) {
  14.        int l,r;cin>>l>>r;
  15.        a[cnt].id = l; a[cnt++].x = 1;
  16.        a[cnt].id = r+1; ar[cnt++].x = -1;
  17.   }
  18.    sort(a,a+cnt,rule);
  19.    int now=0, ans=0;
  20.    for ( int i=0; i<cnt-1; i++ ) {
  21.        now += a[i].x;
  22.        if ( now%2==1 ) {
  23.            ans += a[i+1].id - a[i].id;
  24.       }
  25.   }
  26.    cout << ans << endl;
  27.    
  28.    return 0;
  29. }

1.6 前缀和

  1. 二维前缀和,大概率不会考
  2. *******
  3. *1    *-1
  4. *     *
  5. *******
  6. -1     -1
  7. scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
  8. a[ getid(x1,y1) ] ++;
  9. a[ getid(x1,y2+1) ] ‐‐;
  10. a[ getid(x2+1,y1) ] ‐‐;
  11. a[ getid(x2+1,y2+1) ] ++;
  12. a[ getid(i,j) ] += a[ getid(i‐1,j) ] + a[ getid(i,j‐1) ] ‐ a[ getid(i‐1,j‐1) ];

1.7 STL迭代器

  1. vector<int>::iterator iter; //定义一个名为iter的vector迭代器
  2. map<string,int>::iterator iter; //定义一个名为iter的map迭代器
  3. *iter //对iter进行解引用,返回迭代器iter指向的元素的引用
  4. iter‐>men //对iter进行解引用,获取指定元素中名为men的成员。等效于(*iter).men
  5. ++iter //给iter加1,使其指向容器的下一个元素
  6. iter++
  7. ‐‐iter //给iter减1,使其指向容器的前一个元素
  8. iter‐‐
  9. iter1==iter2 //比较两个迭代器是否相等,当它们指向同一个容器的同一个元素或者都
  10. //指向同同一个容器的超出末端的下一个位置时,它们相等
  11. iter1!=iter2
  12.    
  13.    
  14. int main()
  15. {
  16.    vector<int> a;
  17.    a.push_back(2); a.push_back(8); a.push_back(5);
  18.    vector<int>::iterator it;
  19.    for ( it=a.begin(); it!=a.end(); it++ ) {
  20.        cout << *it << " ";
  21.   }
  22.    
  23.    map<int,string> mp;
  24.    mp[1] = "ab";
  25.    mp[2] = "sx";
  26.    map<int,string>::iterator it;
  27.    for ( it=mp.begin(); it!=mp.end(); it++ ) {
  28.        cout << it->first << " " << it->second << endl;
  29.   }
  30.    return 0;
  31. }
 

1.8 闰年+英语月份星期

闰年共有366天(1-12月分别为31天,29天,31天,30天,31天,30天,31天,31天,30天,31天, 30天,31天) 普通年有365天(1-12月分别为31天,28天,31天,30天,31天,30天,31天,31天,30天,31天, 30天,31天)

四年一闰,百年不闰,四百年又闰
  1. int isyear(int y) {//判断平年闰年
  2. if ( y%400==0 || ( y%4==0 && y%100!=0 ) ) return 1;
  3. return 0;
  4. }

Monday 星期一

Tuesday 星期二

Wednesday 星期三

Thursday 星期四

Friday 星期五

Saturday 星期六

Sunday 星期日,星期天

一月:January二月:February三月:March四月:April五月:May六月:June七月:July八月:August九月:September十月:October十一月:November十二月:December

1.9 离散化

去重函数 + 二分查找

  1. #include <iostream>
  2. #include <string>
  3. #include <algorithm>
  4. using namespace std;
  5. int main()
  6. {
  7.    int a[10]={125,14,88,65,44},b[10]={125,14,88,65,44};
  8.    int n = 5;
  9.    sort(b,b+n); //sort(排序)
  10.    int m = unique(b,b+n) - b; // unique(去重)
  11.    for ( int i=0; i<n; i++ ) {
  12.        a[i] = lower_bound(b,b+m,a[i]) - b + 1;
  13.   }   // lower_bound(查找)
  14.    for ( int i=0; i<n; i++ ) {
  15.        cout << a[i] << " ";
  16.   }
  17.    return 0;
  18. }

第二章 - 数论

2.1 最大公约数和最小公倍数

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. int main()
  5. {
  6.    int n,m;cin >> n >> m;
  7.    cout << __gcd(n,m) << " " << n*m/__gcd(n,m) << endl;
  8.    // 最大公约数, 最小公倍数
  9.    // 2 4 --- 2 4
  10.    // 15 5 --- 5 15
  11.    // 38 4 --- 2 76
  12.    return 0;
  13. }

2.2 素数

欧拉筛

  1. #include <string.h>
  2. #include <iostream>
  3. using namespace std;
  4. const int maxn = 2e6;
  5. int primes[maxn+10],cnt;
  6. bool isprime[maxn+10];
  7. void get_prim()
  8. {
  9.    memset(isprime,true,sizeof(isprime));
  10.    for ( int i=2; i<=maxn; i++ ) {
  11.        if ( isprime[i]==true ) primes[cnt++]=i;
  12.        for ( int j=0; j<cnt&&i*primes[j]<=maxn; j++ ) {
  13.            isprime[ i*primes[j] ] = false;
  14.            if ( i%primes[j]==0 ) break; // 优化点
  15.       }
  16.   }
  17. }
  18. int main()
  19. {
  20.    get_prim();
  21.    for ( int i=0; i<100; i++ ) cout << primes[i] << " ";
  22.    
  23.    return 0;
  24. }

2.3 唯一分解定理

一个数n肯定能被分解成 n = p1^{a1}*p2^{a2}*...*pn^{an}. 因为一个数肯定是由合数和质数构成的,合数又可以分解成质数和合数,最后递归下去就会变成质数的乘积。比如36 = 2 * 2 * 3 * 3

img

2.5 组合数计算

还一种是根据组合数定义来算

C_{n}^{m} =\frac{n!}{m!*(n-m)!} , 预处理出n以内的阶乘及其逆元。

  1. int C( int n, int m )
  2. {
  3.    if ( n<m ) return 0;
  4.    int ans = ((a[n]*b[m])%mod*b[n-m])%mod;
  5.    return ans;
  6. }
  7. a[0]=a[1]=1;
  8. for ( int i=2; i<=1003; i++ ) a[i]=(a[i-1]*i)%mod;
  9. for ( int i=0; i<=1003; i++ ) b[i]=qpow(a[i],mod-2);

2.6 快速幂

记得开long long 和 取模

  1. ll qpow( ll a, ll n )
  2. {
  3.   ll re = 1;
  4.   while ( n ) {
  5.       if ( n&1 ) {
  6.           re = (re*a)%mod;
  7.       }
  8.       n >>= 1;
  9.       a = (a*a)%mod;
  10.   }
  11.   return re;
  12. }

2.7 除法分块

第三章 - 树

3.1 BFS和DFS

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct node {
  4.    int x,y,step;
  5. }t,d;
  6. int nxt[4][2] = {0,1,0,-1,1,0,-1,0};
  7. int via[1005][1005];
  8. int bfs( int x, int y )
  9. {
  10.    queue<node> Q;
  11.    t.x = x; t.y = y; t.step=0;
  12.    Q.push(t);via[t.x][t.y]=1;
  13.    while ( !Q.empty() ) {
  14.        t = Q.front(); Q.pop();
  15.        if ( t.x & t.y 符合条件 ) return step;
  16.        for ( int i=0; i<4; i++ ) {
  17.            下一步的情况...
  18.            d.x = t.x+nxt[i][0];
  19.            d.y = t.y+nxt[i][0];
  20.            d.step = t.step+1;
  21.            if ( d.x & d.y 越界 ) continue ;
  22.            if ( via[d.x][d.y]==0 ) { // 之前没出现过的情况
  23.                Q.push(d);
  24.                via[d.x][d.y] = 1;
  25.           }
  26.       }
  27.   }
  28.    return -1;
  29. }
  30. #include <bits/stdc++.h>
  31. using namespace std;
  32. typedef long long ll;
  33. int a[22];
  34. int n;
  35. ll ans = 0;
  36. void dfs( int node, int presum ) // 当前点,之前点的值
  37. {
  38.    if ( node==n+1 ) {
  39.        return ;
  40.   }
  41.    ll temp = presum|a[node];
  42.    ans += temp;
  43.    dfs(node+1,temp);    // 当前点参与运算
  44.    dfs(node+1,presum);  // 当前点没有参加运算
  45. }
  46. int main()
  47. {
  48.    int i;
  49.    cin >> n;
  50.    for ( i=1; i<=n; i++ ) cin >> a[i];
  51.    bfs(1,0);
  52.    cout << ans << endl;
  53.    return 0;
  54. }

第四章 - 图

4.1 图的存储和遍历

有权图

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int maxn = 2e5+10;
  4. int head[maxn],cnt;
  5. struct edge {
  6.    int to,w,nxt;
  7. }e[maxn];
  8. int n,m;
  9. void add( int u, int v, int w )
  10. {
  11.    e[cnt].to = v;
  12.    e[cnt].w = w;
  13.    e[cnt].nxt = head[u];
  14.    head[u] = cnt++;
  15. }
  16. int main()
  17. {
  18.    memset(head,-1,sizeof(head)); cnt=0;
  19.    cin>>n>>m;
  20.    for ( int i=0; i<m; i++ ) {
  21.        int u,v,w;cin>>u>>v>>w;
  22.        add(u,v,w); // 单向建边
  23.        add(v,u,w);
  24.   }
  25.    int x = 3; // 遍历点x=3的临边
  26.    for ( int i=head[x]; i!=-1; i=e[i].nxt ) {
  27.        int y = e[i].to;
  28.        int w = e[i].w;
  29.        一些操作.....
  30.   }
  31.    
  32.    return 0;
  33. }

无权图

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int maxn = 2e5+10;
  4. vector<int> G[maxn];
  5. int main()
  6. {
  7.    cin>>n>>m;
  8.    for ( int i=0; i<m; i++ ) {
  9.        int u,v;scanf("%d %d",&u,&v);
  10.        e[i].u=min(u,v);e[i].v=max(u,v);
  11.        G[u].push_back(v);
  12.        G[v].push_back(u);
  13.   }
  14.    // 遍历u点相邻的点,无权图无法存边权
  15.    for ( int i=0; i<G[u].size(); i++ ) {
  16.        int v = G[u][i];
  17.        // u->v有一条边...
  18.   }
  19.    
  20.    return 0;
  21. }

4.2 最短路

P4779 【模板】单源最短路径(标准版)

已ac放心看

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 2e5+10;
  4. int head[maxn],cnt;
  5. struct edge{
  6.   int to,nxt,w;
  7. }e[maxn*2];
  8. struct node {
  9.   int v,dis;
  10. }t,d;
  11. int n,m,s;
  12. int dis[maxn],via[maxn];
  13. bool operator<( const node& a, const node& b )
  14. {
  15.   return a.dis>b.dis; //重点!!是大于
  16. }
  17. void add( int u, int v, int w )
  18. {
  19.   e[cnt].to = v;
  20.   e[cnt].w = w;
  21.   e[cnt].nxt = head[u];
  22.   head[u] = cnt++;
  23. }
  24. void dij( int s )
  25. {
  26.   memset(via,0,sizeof(via));
  27.   memset(dis,0x3f3f3f3f,sizeof(dis));
  28.   priority_queue<node> Q;
  29.   t.v = s; t.dis=0;
  30.   Q.push(t);
  31.   while ( !Q.empty() ) {
  32.       if ( via[ Q.top().v ]==1 ) {
  33.           Q.pop();
  34.           continue ;
  35.       }
  36.       t = Q.top(); Q.pop();
  37.       int u = t.v;
  38.       dis[u] = t.dis;
  39.       via[u] = 1;
  40.       for ( int i=head[u]; i!=-1; i=e[i].nxt ) {
  41.           int v = e[i].to, w=e[i].w;
  42.           if ( via[v]==0 && dis[v]>dis[u]+w ) {
  43.               dis[v] = dis[u]+w;
  44.               d.v = v;
  45.               d.dis = dis[v];
  46.               Q.push(d);
  47.           }
  48.       }
  49.   }
  50. }
  51. int main()
  52. {
  53.   memset(head,-1,sizeof(head)); cnt=0;
  54.   cin>>n>>m>>s;
  55.   for ( int i=0; i<m; i++ ) {
  56.       int u,v,w;scanf("%d %d %d",&u,&v,&w);
  57.       add(u,v,w);
  58.   }
  59.   dij(s);
  60.   for ( int i=1; i<n; i++ ) printf("%d ",dis[i]);
  61.   printf("%d\n",dis[n]);
  62.   return 0;
  63. }

4.3 最小生成树

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct node {
  4. int from,to,w;
  5. }a[105*105];
  6. int n,cnt,ans,pos;
  7. int pre[105];
  8. int rule( node a, node b )
  9. {
  10. return a.w<b.w;
  11. }
  12. int root( int x )
  13. {
  14. if ( pre[x]!=x ) {
  15. pre[x] = root(pre[x]);
  16. }
  17. return pre[x];
  18. }
  19. int join( int a, int b, int w )
  20. {
  21. int x = root(a);
  22. int y = root(b);
  23. if ( x!=y ) {
  24. pre[x] = pre[y];
  25. ans += w;
  26. pos ++;
  27. }
  28. }
  29. int main() {
  30. cin>>n;
  31. for ( int i=0; i<=n; i++ ) pre[i]=i;
  32. cnt = 0; ans=0; pos=0;
  33. for ( int i=1; i<=n; i++ ) {
  34. for ( int j=1; j<=n; j++ ) {
  35. int x;scanf("%d",&x);
  36. if ( i==j ) continue;
  37. a[cnt].from = i;
  38. a[cnt].to = j;
  39. a[cnt++].w = x;
  40. }
  41. }
  42. sort(a,a+cnt,rule);
  43. for ( int i=0; i<cnt; i++ ) {
  44. join(a[i].from,a[i].to,a[i].w);
  45. if ( pos==n-1 ) break;
  46. }
  47. cout << ans << endl;
  48. return 0;
  49. }

4.4 拓扑排序

  1. void topu()
  2. {
  3. queue<int> Q; // 队列只存入度为0的点
  4. for ( int i=1; i<=n; i++ ) {
  5. if ( in[i]==0 ) Q.push(i);
  6. }
  7. vector<int> ans; // 存拓扑序列
  8. while ( !Q.empty() ) {
  9. int t = Q.front(); Q.pop(); // 选一个入度为0的点出来
  10. ans.push_back(t);
  11. for ( int i=head[t]; i!=-1; i=e[i].nxt ) {
  12. int to = e[i].to;
  13. in[to]--; // 相连点度数--
  14. if ( in[to]==0 ) Q.push(to);
  15. }
  16. }
  17. return 0;
  18. }

4.5 dfs判负环 *

第五章 - 动态规划

5.1 背包问题

01 背包 有n 种不同的物品(每个物品只有一件),每个物品有两个属性,weight 体积,value 价值,现在给一个容量为 w 的背包,问最多可带走多少价值的物品。

完全背包 如果物品不计件数,就是每个物品不只一件的话。

01背包问题完全背包问题 代码非常相似 一个是从后往前遍历,一个是从前往后遍历。

01背包

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int dp[1005];
  4. int price[1005];
  5. int weight[1005];
  6. int main()
  7. {
  8. int n,tot;
  9. while ( cin>>n>>tot ) {
  10. memset(dp,0,sizeof(dp));
  11. for ( int i=1; i<=n; i++ ) cin>>weight[i]>>price[i];
  12. for ( int i=1; i<=n; i++ ) {
  13. for ( int j=tot; j>=1; j-- ) {
  14. if ( j>=weight[i] ) {
  15. dp[j] = max( dp[j], dp[j-weight[i]]+price[i] );
  16. }
  17. }
  18. }
  19. cout << dp[tot] << endl; // 最多能装多少价值的货物
  20. }
  21. return 0;
  22. }

完全背包

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int dp[1005];
  4. int price[1005];
  5. int weight[1005];
  6. int main()
  7. {
  8. int n,tot;
  9. while ( cin>>n>>tot ) {
  10. memset(dp,0,sizeof(dp));
  11. for ( int i=1; i<=n; i++ ) cin>>weight[i]>>price[i];
  12. for ( int i=1; i<=tot; i++ ) {
  13. for ( int j=1; j<=tot; j++ ) {
  14. if ( j>=weight[i] ) {
  15. dp[j] = max( dp[j], dp[j-weight[i]]+price[i] );
  16. }
  17. }
  18. }
  19. cout << dp[tot] << endl; // 最多能装多少价值的货物
  20. }
  21. return 0;
  22. }

恰好装满问题

朴素的背包代码是求小于等于背包体积能装的最大值,但有些时候题目要求背包需要恰好完全装满。

是否恰好装满的解法不同只在于初始值的不同

恰好装满:

求最大值时,除了dp[0] 为0,其他都初始化为无穷小 -0x3f3f3f3f ,for循环里取max

求最小值时,除了dp[0] 为0,其他都初始化为无穷大 0x3f3f3f3f ,for循环里取min

不必恰好装满:

求最大值时,初始化为0

求最小值时,初始化为0

5.2 最大连续子序列和

贪心,for循环累加,小于0,设成0

5.3 最长不下降子序列(LIS)

5.4 最长公共子序列(LCS)

5.5 最长回文子串

5.6 DAG最长路

第六章 - 字符串

6.1 字符串hash

6.2 KMP算法

给定两个字符串 s 和 t ,判断 t 是否为 s 的子串。

第七章 - 数据结构

7.1 线段树lazy模板

7.2 权值线段树

7.3 并查集

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n,m,k,ans;
  4. int pre[100005];
  5. struct node {
  6. int from,to,w;
  7. }e[100005*3];
  8. int rule( node a, node b )
  9. {
  10. return a.w>b.w;
  11. }
  12. int root( int x )
  13. {
  14. if ( x!=pre[x] ) {
  15. pre[x] = root(pre[x]);
  16. }
  17. return pre[x];
  18. }
  19. int join( int u, int v, int w )
  20. {
  21. int x = root(u);
  22. int y = root(v);
  23. if ( x!=y ) {
  24. pre[x] = y;
  25. k --;
  26. ans += w;
  27. }
  28. }
  29. int main()
  30. {
  31. ans = 0;
  32. cin>>n>>m>>k;
  33. for ( int i=0; i<=n; i++ ) pre[i]=i;
  34. for ( int i=0; i<m; i++ ) {
  35. int u,v,w;scanf("%d %d %d",&u,&v,&w);
  36. e[i].from=u;
  37. e[i].to = v;
  38. e[i].w = w;
  39. }
  40. sort(e,e+m,rule);
  41. for ( int i=0; i<m; i++ ) {
  42. join(e[i].from,e[i].to,e[i].w);
  43. if ( k==0 ) break;
  44. }
  45. cout << ans << endl;
  46. return 0;
  47. }

7.4 单调栈&单调队列

对于单调队列,我们这样子来定义:

  • 1、维护区间最值

  • 2、去除冗杂状态 如上题,区间中的两个元素a[i],a[j](假设现在再求最大值) 若 j>i且a[j]>=a[i] ,a[j]比a[i]还大而且还在后面(目前a[j]留在队列肯定比a[i]有用,因为你是往后推, 核心思想 !!!)

  • 3、保持队列单调,最大值是单调递减序列,最小值反之

  • 4、最优选择在队首

单调队列实现的大致过程: 1、维护队首(对于上题就是如果队首已经是当前元素的m个之前,则队首就应该被删了,head++) 2、在队尾插入(每插入一个就要从队尾开始往前去除冗杂状态,保持单调性)

简单举例应用 数列为:6 4 10 10 8 6 4 2 12 14 N=10,K=3; 那么我们构造一个长度为3的单调递减队列: 首先,那6和它的位置0放入队列中,我们用(6,0)表示,每一步插入元素时队列中的元素如下 插入6:(6,0); 插入4:(6,0),(4,1); 插入10:(10,2); 插入第二个10,保留后面那个:(10,3); 插入8:(10,3),(8,4); 插入6:(10,3),(8,4),(6,5); 插入4,之前的10已经超出范围所以排掉:(8,4),(6,5),(4,6); 插入2,同理:(6,5),(4,6),(2,7); 插入12:(12,8); 插入14:(14,9); 那么f(i)就是第i步时队列当中的首元素:6,6,10,10,10,10,8,6,12,14 同理,最小值也可以用单调队列来做。

单调队列的时间复杂度是O(N),因为每个数只会进队和出队一次,所以这个算法的效率还是很高的。 注意:建议直接用数组模拟单调队列,因为系统自带容器不方便而且不易调试,同时,每个数只会进去一次,所以,数组绝对不会爆,空间也是S(N),优于堆或线段树等数据结构。

更重要的:单调是一种思想,当我们解决问题的时候发现有许多冗杂无用的状态时,我们可以采用单调思想,用单调队列或类似于单调队列的方法去除冗杂状态,保存我们想要的状态,

  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. using namespace std;
  5. const int maxn = 1e6+10;
  6. struct node {
  7. int date,time;
  8. } v[maxn],t,d; // 模拟单调队列
  9. int n,k;
  10. int a[maxn];
  11. int Max[maxn];
  12. int Min[maxn];
  13. int cnt;
  14. int head=1,tail=0; // 记住这个设定
  15. void getmax()
  16. {
  17. head=1;tail=0;
  18. t.date=a[0]; t.time=k; v[++tail]=t; // 把第一个值放进队列
  19. Max[0] = v[head].date;
  20. for ( int i=1; i<n; i++ ) {
  21. if ( v[head].time<=i ) head++; // 检验队头元素是否过期
  22. t.date = a[i];
  23. t.time = i+k;
  24. while ( t.date>=v[tail].date && head<=tail ) {
  25. tail --; // 当前元素从队尾插入,并保持队列单调
  26. }
  27. v[++tail] = t;
  28. Max[i] = v[head].date; // 更新当前状态的答案
  29. }
  30. for ( int i=k-1; i<n-1; i++ ) {
  31. cout << Max[i] << " ";
  32. }
  33. cout << Max[n-1] << endl;
  34. }
  35. void getmin()
  36. {
  37. head=1;tail=0;
  38. t.date=a[0]; t.time=k; v[++tail]=t;
  39. Min[0] = v[head].date;
  40. for ( int i=1; i<n; i++ ) {
  41. if ( v[head].time<=i ) head++;
  42. t.date = a[i];
  43. t.time = i+k;
  44. while ( t.date<=v[tail].date && head<=tail ) {
  45. tail --;
  46. }
  47. v[++tail] = t;
  48. Min[i] = v[head].date;
  49. }
  50. for ( int i=k-1; i<n-1; i++ ) {
  51. cout << Min[i] << " ";
  52. }
  53. cout << Min[n-1] << endl;
  54. }
  55. int main()
  56. {
  57. cin >> n >> k;
  58. for ( int i=0; i<n; i++ ) {
  59. scanf("%d",&a[i]);
  60. }
  61. getmin();
  62. getmax();
  63. return 0;
  64. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/870188
推荐阅读
相关标签
  

闽ICP备14008679号