蓝桥杯模拟赛 4

A题 刷题统计

签到题,简单计算一下即可,一周为一个周期

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<map>
#define IOS ios::sync_with_stdio(false)
#define CC cin.tie(nullptr),cout.tie(nullptr)
#define int long long
#define f first
#define s second

using namespace std;

typedef pair<int ,int> PII;
typedef double D;
const int N = 100010, M = 1e5 + 10;

int a, b, n;

void solve() {
    cin >> a >> b >> n;
    int t = n % (5 * a + 2 * b);
    int k = n / (5 * a + 2 * b);
    int ans = 0;
    int l[] = {a, a, a, a, a, b, b};
    for (int i = 0; t > 0; i++)t -= l[i], ans++;
    cout << ans + k * 7 << endl;
}

signed main() {
    IOS;
    CC;
    int h_h = 1;
    //cin >> h_h;
    while (h_h--) solve();
    return 0;
}

C题 求和

利用前缀和的知识,每个数和他后面的每个数相乘,提出公因子,剩下的用前缀和求即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<map>
#define IOS ios::sync_with_stdio(false)
#define CC cin.tie(nullptr),cout.tie(nullptr)
#define int long long
#define f first
#define s second

using namespace std;

typedef pair<int ,int> PII;
typedef double D;
const int N = 100010, M = 1e5 + 10;

int s[2*N], a[2*N];
int n, sum, ans;

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i++)cin >> a[i], s[i] = s[i - 1] + a[i];
    for (int i = 1; i <= n; i++)ans += a[i] * (s[n] - s[i]);
    cout << ans << endl;
}

signed main() {
    IOS;
    CC;
    int h_h = 1;
    //cin >> h_h;
    while (h_h--) solve();
    return 0;
}

D题 修建灌木

这道题应该是属于找规律,它最高是什么时候呢,就是从这个点开始,移动到头或尾,再折回来到这点所经过的距离,左右两边求最大值即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<map>
#define IOS ios::sync_with_stdio(false)
#define CC cin.tie(nullptr),cout.tie(nullptr)
#define int long long
#define f first
#define s second

using namespace std;

typedef pair<int ,int> PII;
typedef double D;
const int N = 100010, M = 1e5 + 10;

int s[2*N], a[2*N];
int n, sum, ans;

void solve() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        cout << max(2 * i, 2 * (n - 1 - i)) << endl;
    }
}

signed main() {
    IOS;
    CC;
    int h_h = 1;
    //cin >> h_h;
    while (h_h--) solve();
    return 0;
}

E题 李白打酒加强版

这是一道动态规划的题目,我们可以先定义一下集合的含义,dp[i][j][k] 表示为前i次,有j次遇到店,剩下酒为k斗。因为n,m最大值为100,因此当k>100之后,该情况必然不合法。

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 110, MOD = 1e9 + 7;

int n, m;
int f[N][N][N];

int main()
{
    cin >> n >> m;

    f[0][0][2] = 1;
    for (int i = 0; i <= n; i ++ )
        for (int j = 0; j <= m; j ++ )
            for (int k = 0; k <= m; k ++ )
            {
                int& v = f[i][j][k];
                if (i && k % 2 == 0) v = (v + f[i - 1][j][k / 2]) % MOD;
                if (j) v = (v + f[i][j - 1][k + 1]) % MOD;
            }

    cout << f[n][m - 1][1] << endl;
    return 0;
}

H题 卡牌

容易知道是把空白牌用到少的类上,这题思路就是直接二分答案了\n\n如果当前类牌不够mid张,当然是将空白的编变成该类牌,一是看是否超过了b数组的限制,二是看是否超过了最大空白牌数量。\n\n直到最后也是没有被返回NO,那么返回YES

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define M 1000005
LL n,m;
LL a[M],b[M];
int check(int mid){
    LL sum=0;
    for(int i=1;i<=n;i++){
        if(a[i]<mid){
            if(mid-a[i]>b[i]) return 0;
            sum+=mid-a[i];
            if(sum>m) return 0;
        }
    }
    return 1;
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++) scanf("%lld",&b[i]);
    LL l=0,r=n*2,ans=0;
    while(l<=r){
        LL mid=(l+r)/2;
        if(check(mid)){
            l=mid+1;
            ans=mid;
        }else{
            r=mid-1;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

SMU Winter 2023 Round #13 (Div.2)

B题 BM算日期

这题只需注意一下,左边取较小的,右边取较大的即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<map>
#define IOS ios::sync_with_stdio(false)
#define CC cin.tie(nullptr),cout.tie(nullptr)
#define ll long long
#define f first
#define s second

using namespace std;

typedef pair<int ,int> PII;
typedef double D;
const int N = 100010, M = 1e5 + 10;

void solve() {
    int y, a, l, r;
    cin >> y >> a;
    l = min(y, y + a), r = max(y, y + a);
    if (y + a > 9999) {
        int t = y + a - 9999;
        r = max(y, 9999 - t);
        l = min(y, 9999 - t);
    }
    int cnt = 0;
    for (int i = l; i <= r; i++) {
        if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
            cnt++;
    }
    cout << cnt << endl;
}

int main() {
    IOS;
    CC;
    int h_h = 1;
    cin >> h_h;
    while (h_h--) solve();
    return 0;
}

E题 BM充饥

签到题目

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#define IOS ios::sync_with_stdio(false)
#define CC cin.tie(nullptr),cout.tie(nullptr)
#define ll long long
#define f first
#define s second

using namespace std;

typedef pair<int ,int> PII;
typedef double D;
const int N = 100010, M = 1e5 + 10;

void solve() {
    string s;
    cin >> s;
    printf(R"( __      _____
|  | ___/ ____\____
|  |/ /\   __\/ ___\
|    <  |  | \  \___
|__|_ \ |__|  \___  >
     \/           \/)");
}

int main() {
    IOS;
    CC;
    int h_h = 1;
    //cin >> h_h;
    while (h_h--) solve();
    return 0;
}

H题 Hsueh- Draw Progress

按照题目模拟即可,有一个细节,要先算出小数在保留后两位,那我们的操作就是除成小数以后乘以100再强制类型转换为int即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#define IOS ios::sync_with_stdio(false)
#define CC cin.tie(nullptr),cout.tie(nullptr)
#define ll long long
#define f first
#define s second

using namespace std;

typedef pair<int ,int> PII;
typedef double D;
const int N = 100010, M = 1e5 + 10;

void solve() {
    int n, m;
    cin >> n >> m;
    cout << '[';
    for (int i = 0; i < m; i++)cout << '#';
    for (int i = 0; i < n - m; i++)cout << '-';
    cout << "] ";
    cout << (int) ((D) m / n * 100) << '%' << endl;
}

int main() {
    IOS;
    CC;
    int h_h = 1;
    cin >> h_h;
    while (h_h--) solve();
    return 0;
}

J题 大扫除

这题我们可以一层一层的搜,每层的垃圾用set来维护,自动去重,没遍历完一层就把它加到答案里并且清空set继续遍历下一层。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#define IOS ios::sync_with_stdio(false)
#define CC cin.tie(nullptr),cout.tie(nullptr)
#define ll long long
#define f first
#define s second

using namespace std;

typedef pair<int ,int> PII;
typedef double D;
const int N = 100010, M = 1e5 + 10;

void solve() {
    set<char> st;
    int n;
    cin >> n;
    int cnt=0;
    for (int i = 0; i < n; i++) {
        string s;
        cin >> s;
        for (int j = 0; j < s.size(); j++) {
            if (s[j] != '.')
                st.insert(s[j]);
        }
        //for(auto i:st)cout<<i<<' ';cout<<endl;
        cnt+=(int)st.size();
        st.clear();
    }
    cout << cnt << endl;
}

int main() {
    IOS;
    CC;
    int h_h = 1;
    cin >> h_h;
    while (h_h--) solve();
    return 0;
}

J题 旅游

数字位数过多可以用字符串来存,然后遍历字符串,最后判断结果即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#define IOS ios::sync_with_stdio(false)
#define CC cin.tie(nullptr),cout.tie(nullptr)
#define ll long long
#define f first
#define s second

using namespace std;

typedef pair<int ,int> PII;
typedef double D;
const int N = 100010, M = 1e5 + 10;

void solve() {
    int cnt = 0;
    for (int i = 0; i < 4; i++) {
        string s;
        cin >> s;
        int sum = 0;
        for (int j = 0; j < s.size(); j++) {
            sum += s[j] - '0';
        }
        if(sum==6||sum>=16)cnt++;
    }
    if (cnt == 4)cout << "Oh my God!!!!!!!!!!!!!!!!!!!!!" << endl;
    if (cnt == 3)cout << "Bao Bao is a SupEr man///!" << endl;
    if (cnt == 2)cout << "BaoBao is good!!" << endl;
    if (cnt == 1)cout << "Oh dear!!" << endl;
    if (cnt == 0)cout << "Bao Bao is so Zhai......" << endl;
}

int main() {
    IOS;
    CC;
    int h_h = 1;
    //cin >> h_h;
    while (h_h--) solve();
    return 0;
}

D题 Palindrome Hard Problem

这题是典型的贪心,因为每个字符就可以构成回文串,所一回文串最多就是所有字符串加在一起的长度。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#define IOS ios::sync_with_stdio(false)
#define CC cin.tie(nullptr),cout.tie(nullptr)
#define ll long long
#define f first
#define s second

using namespace std;

typedef pair<int ,int> PII;
typedef double D;
const int N = 100010, M = 1e5 + 10;

void solve() {
    int n;
    cin >> n;
    string s;
    int sum=0;
    for (int i = 0; i < n; i++) {
        string s1;
        cin >> s1;
        s+=s1;
    }
    cout << s.size() << endl;
}

int main() {
    IOS;
    CC;
    int h_h = 1;
    //cin >> h_h;
    while (h_h--) solve();
    return 0;
}

SMU Winter 2023 Round #7 (Div.2)

A题 解开束缚缠丝Ⅱ

题意:求给出的n个字符最长可以组成多长的回文串。

思路:就是统计字符出现的次数,要么全部是偶数全部可以构成回文串,如果有奇数,那么只有其中一个奇数的字符串可以放入回文串中,用map来做就可以了。

#include<bits/stdc++.h>
 using namespace std;
 int main() {
     int t;
     cin>>t;
     while(t--){
         int n;
         cin>>n;
         map <char,int> mp;
         int ans=0;
         for(int i=0;i<n;i++){
             char ch;
             cin>>ch;
             mp[ch]++;
         }
         for(auto i:mp){
             if(i.second%2!=0)ans++;
         }
         //cout<<ans<<' ';
         cout<<n-ans+1<<endl;
     }
     return 0;
 }

B题 7 的意志

题意:求有最多几个区间的和为7777

思路:先进行前缀和预处理,然后枚举每一个可能的区间和的左端点,寻找可行的右端点。一个左端点最多只有一个可行的右端点进行匹配

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, ans;
int a[100005], s[100005];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    ll t;
    cin>>t;
    while (t--) {
        cin >> n;
        s[0] = ans = 0;
        for (int i = 1; i <= n; ++i) {
            cin >> a[i];
            s[i] = s[i - 1] + a[i];
        }
        for (int i = 1; i <= n; ++i) {
            ll tar = s[i - 1] + 7777;
            ll x = lower_bound(s + 1, s + n + 1, tar) - s;
            if (s[x] == tar) ans++;
        }
        cout << ans << '\n';
    }
    return 0;
}

F题 月光奏鸣曲

题意:给你两个正方形的数字矩阵,可以逆时针和顺时针转动,问最少转几次让两个矩阵相等。

思路:肯定只能往一个方向转,不然只要有一个向另外一个方向转了,就会抵消本方向的一次,相当于没有转,但是操作次数却多了两次,题目求最少,并且做多只有可能转三次,第四次就回原位置了,写四个转零次,一次,两次,三次的函数判断一下即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

int n;
int a[25][25], b[25][25];

bool check0() {
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (b[i][j] != a[i][j]) return false;
        }
    }
    return true;
}

bool check1() {
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (b[i][j] != a[n - j + 1][i]) return false;
        }
    }
    return true;
}

bool check2() {
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (b[i][j] != a[j][n - i + 1]) return false;
        }
    }
    return true;
}

bool check3() {
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (b[i][j] != a[n - i + 1][n - j + 1]) return false;
        }
    }
    return true;
}

void main2() {
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cin >> a[i][j];
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cin >> b[i][j];
        }
    }
    if (check0()) cout << 0 << '\n';
    else if (check1()) cout << 1 << '\n';
    else if (check2()) cout << 1 << '\n';
    else if (check3()) cout << 2 << '\n';
    else cout << -1 << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    LL _;
    cin >> _;
//	_ = 1;
    while (_--) main2();
    return 0;
}


H题 简单的 LRU 问题

就是根据题目所说模拟一下就可以了,但是有点复杂,要耐得住性子

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

int n, m, mx;
int a[105][10];
string hx = "0123456789abcdef";


int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n >> m;
    mx = 0;
    cout << "+------+";
    for (int i = 0; i < n; ++i) {
        cout << "--------+";
    }
    cout << '\n';
    cout << "|      |";
    for (int i = 0; i < n; ++i) {
        cout << "  0x";
        int a = i / 16, b = i % 16;
        cout << hx.substr(a, 1) << hx.substr(b, 1) << "  |";
    }
    cout << '\n';
    cout << "+------+";
    for (int i = 0; i < n; ++i) {
        cout << "--------+";
    }
    cout << '\n';
    for (int i = 0; i < m; ++i) {
        int x; cin >> x;
        if (i == 0) a[0][0] = x;
        else {
            int have = 0;
            for (int j = 0; j <= mx; ++j) {
                if (a[i - 1][j] == x) {
                    have = 1; break;
                }
            }
            if (have) {
                int k = 0;
                for (int j = 0; j <= mx; ++j) {
                    if (a[i - 1][j] == x) continue;
                    a[i][k++] = a[i - 1][j];
                }
                a[i][mx] = x;
            }
            else {
                if (mx < n - 1) {
                    for (int j = 0; j <= mx; ++j) {
                        a[i][j] = a[i - 1][j];
                    }
                    a[i][++mx] = x;
                }
                else {
                    int k = 0;
                    for (int j = 1; j <= mx; ++j) {
                        a[i][k++] = a[i - 1][j];
                    }
                    a[i][mx] = x;
                }
            }
        }
        cout << "| 0x";
        int A, B, C, D; A = i / 16; B = i % 16;
        cout << hx.substr(A, 1) << hx.substr(B, 1) << " |";
        for (int j = 0; j <= mx; ++j) {
            cout << " 0x";
            int tmp = a[i][j];
            A = tmp / 4096; tmp -= A * 4096;
            B = tmp / 256; tmp -= B * 256;
            C = tmp / 16; tmp -= C * 16;
            D = tmp;
            cout << hx.substr(A, 1) << hx.substr(B, 1);
            cout << hx.substr(C, 1) << hx.substr(D, 1) << " |";
        }
        for (int j = mx + 1; j < n; ++j) {
            cout << "        |";
        }
        cout << '\n';
        cout << "+------+";
        for (int i = 0; i < n; ++i) {
            cout << "--------+";
        }
        cout << '\n';
    }
    return 0;
}

I题 好想听肆宝唱歌啊

题意:给你几首个的名字以及喜爱它的程度,数字越大喜爱程度越高,再给你个数字k,就是最爱的前k首歌曲已经点了,现在要点目前情况下最喜爱的歌曲,输出该歌曲的名字。

思路:使用一个结构体进行排序,如果输出k+1首歌曲的名字就可以了。

#include<bits/stdc++.
using namespace std;
typedef long long LL;
const int N=100010;
int n;

struct S {
    int w;
    string x;
}s[N];


bool cmp(S a,S b){
    return a.w>b.w;
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> s[i].w >> s[i].x;
    sort(s + 1, s + n + 1, cmp);
    int k;
    cin >> k;
    cout << s[k + 1].x;
    return 0;
}



J 题 毁灭凤凰人

#include<bits/stdc++.h>
using namespace std;
int n, m;
int mxa = 0, a = 0, b = 0;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        int res, x;
        cin >> res;
        if (res == 0) {
            cin >> x;
            mxa = max(mxa, x);
        } else if (res == 1) a = 1;
        else b = 1;
    }
    if (m == 0 && mxa >= 2500 && a) {
        cout << "haoye\n";
        return 0;
    } else if (m == 1 && mxa > 2100 && a) {
        cout << "haoye\n";
        return 0;
    } else if (b && n > 1) {
        cout << "haoye\n";
        return 0;
    } else cout << "QAQ\n";
    return 0;
}

K题 欢迎来到杭师大

题意:给你一个n,输出n个Welcome to HZNU,每个要换行

思路:先定义一个字符串,用个循环输出即可。

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
int main() {
    IOS;
    int n;
    cin>>n;
    string s="Welcome to HZNU";
    while(n--){
        cout<<s<<'\n';
    }
    return 0;
}

L题 Ayanoto 变形记

题意:给n个点,每次条x步,问再其中一个位置,能不能跳回原来的位置

思路:我们可以知道,总共跳的步数就是两个数的最小公倍数,但两个不为零的数肯定有最小公倍数,所以只要跳的x不为零,都可以,为零就不行。

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
#define ll long long
using namespace std;
int main() {
    IOS;
    ll t;
    cin>>t;
    while(t--) {
        ll a, b;
        cin >> a >> b;
        if (b == 0)cout << "no" << '\n';
        else cout << "yes" << '\n';
    }
    return 0;
}

M题 龙学长的教诲

题意:给你一个字符串,他的顺序是1,3,5,6,4,2这样的顺序,但他正确的顺序是1,2,3,4,5,6,将正确的输出出来,标点符号在最后

思路:再读入的时候,当这个字符串的结尾有标点符号时就结束读入,将标点符号记下来,按顺序输出就可以了,记得最后加标点符号,再注意一下具体的格式。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

int n;
string x[1005];
char op;

void print(int id) {
    if (id != n) cout << x[id];
    else {
        int len = x[id].length();
        for (int i = 0; i < len - 1; ++i) {
            cout << x[id][i];
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int t;
    cin >> t;
    while (t--){
        n=0;
        while (cin >> x[++n]) {
            int len = x[n].length();
            if (x[n][len - 1] == '.' || x[n][len - 1] == '!' || x[n][len - 1] == '?') {
                op = x[n][len - 1];
                break;
            }
        }
        for (int i = 1; i <= n / 2; ++i) {
            print(i);
            cout << ' ';
            print(n - i + 1);
            if (i < n / 2 or n % 2 == 1)cout << ' ';
        }
        if (n % 2 == 1) {
            print(n / 2 + 1);
        }
        cout << op<< '\n';
    }
    return 0;
}

哈希表

有两种方法。

拉链法
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 100003;

int h[N],e[N],ne[N],idx;
int n;

void insert(int x){
    int k=(x%N+N)%N;
    e[idx]=x,ne[idx]=h[k],h[k]=idx++;
}

bool query(int x){
    int k=(x%N+N)%N;
    for(int i=h[k];i!=-1;i=ne[i]){
        if(e[i]==x)return true;
    }
    return false;
}

int main()
{
    cin>>n;
    memset(h,-1,sizeof h);
    while(n--){
        char op;
        int x;
        cin>>op>>x;
        if(op=='I')insert(x);
        else {
            if(query(x))puts("Yes");
            else puts("No");
        }
    }
    return 0;
}
开放寻址法
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 300007, inf=0x3f3f3f3f;

int h[N];
int n;

int find(int x){
    int k=(x%N+N)%N;
    while(h[k]!=inf&&h[k]!=x){
        k++;
        if(k==N-1)k=0;
    }
    return k;
}

int main()
{
    cin>>n;
    memset(h, 0x3f, sizeof h);
    while (n -- ){
        char op;
        int x;
        cin>>op>>x;
        if(op=='I')h[find(x)]=x;
        else {
            if(h[find(x)]!=inf)puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

字符串哈希

处理字符串问题的利器

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef unsigned long long ull;

const int N = 100010, P=131;

ull p[N], h[N];
int n,m;
char s[N];

ull getSum(int l,int r){
    return h[r]-h[l-1]*p[r-l+1];
}

int main()
{
    cin>>n>>m>>s+1;
    p[0]=1;
    for(int i=1;i<=n;i++){
        h[i]=h[i-1]*P+s[i];
        p[i]=p[i-1]*P;
    }
    
    while (m -- ){
        int l1,r1,l2,r2;
        cin>>l1>>r1>>l2>>r2;
        if(getSum(l1,r1)==getSum(l2,r2))puts("Yes");
        else puts("No");
    }
    return 0;
}

单调栈

#include <iostream>
#include <cstring>
#include <algorithm>
#include<stack>

using namespace std;

const int N = 100010;

int n;
int a[N];

int main()
{
    stack<int> st;
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    for(int i=0;i<n;i++){
        while(st.size()&&a[i]<=st.top())st.pop();
        if(st.size())cout<<st.top()<<' ';
        else cout<<-1<<' ';
        st.push(a[i]);
    }
    return 0;
}

单调队列

#include <iostream>
#include <cstring>
#include <algorithm>
#include<queue>

using namespace std;

const int N = 1000010;

int q[N];
int n, k;
int a[N];
int tt=-1, hh;

int main() {
    cin >> n >> k;
    for(int i = 0; i < n; i ++)cin >> a[i];
    for (int i = 0; i < n; i++) {
        if (hh <= tt && i - k + 1 > q[hh])hh ++;;
        while (hh <= tt && a[q[tt]] >= a[i])tt--;
        q[++tt] = i;
        if (i+1>=k)cout << a[q[hh]] << ' ' ;
    }
    cout<<endl;
    tt = -1, hh = 0;
    for (int i = 0; i < n; i++) {
        if (hh <= tt && i - k + 1 > q[hh])hh ++;;
        while (hh <= tt && a[q[tt]] <= a[i])tt--;
        q[++tt] = i;
        if (i+1>=k)cout << a[q[hh]] << ' ' ;
    }
    return 0;
}