这个题,看了题解之后大家都是用到了一个数学结论,emmm我一开始补题并没有想到这个结论,我想给大家说一下如果用栈怎么做(题解里看到有大佬说用栈做的),这里详细展开一下:
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
    int t;
    cin >> t;
    while (t--) // 最贪心的选择是尽早选
    {
        int n;
        cin >> n;
        stack<pair<int, int>> q;
        vector<int> a(n + 2, 0);
        a[n + 1] = -1;
        vector<int> ans(n + 2, 0);
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
        }
        q.push({a[1], 1});
        for (int i = 2; i <= n; i++)
        {
            if (!q.empty() && q.top().first == a[i] && a[i + 1] != a[i])
            {
                while (!q.empty() && q.top().first == a[i])
                {
                    q.pop();
                }
            }
            else
            {
                if (!q.empty() && a[i] < q.top().first)
                {
                    ans[i] = a[i];
                    while (!q.empty() && q.top().first > a[i])
                    {
                        auto [zhi, id] = q.top();
                        ans[id] = zhi;
                        q.pop();
                    }
                    if (!q.empty() && a[i] != a[i + 1] && q.top().first == a[i])
                    {
                        while (!q.empty() && a[i] != a[i + 1] && q.top().first == a[i])
                        {
                        q.pop();
                        }
                    }
                    else
                    {
                        q.push({a[i], i});
                        continue;
                    }
                }
                else
                {
                    q.push({a[i], i});
                }
            }
        }
        while (!q.empty())
        {
            auto [zhi, id] = q.top();
            q.pop();
            ans[id] = zhi;
        }
        for (int i = 1; i <= n; i++)
        {
            if (ans[i] != 0)
            {
                if (a[i - 1] > a[i]&&ans[i-1]==0)
                {
                    ans[i] = 0;
                }
            }
        }
          for (int i = n; i >=1; i--)
        {
            if (ans[i] != 0)
            {
                if (a[i + 1] > a[i]&&ans[i+1]==0)
                {
                    ans[i] = 0;
                }
            }
        }
        int tai = 1;
        for (int i = 1; i <= n; i++)
        {
            if (ans[i] != 0)
            {
                tai = 0;
                break;
            }
        }
        if (!tai)
            cout << "No" << '\n';
        else
        {
            cout << "Yes" << '\n';
        }
    }
}
乍一看,很长其实给我的感觉就像开心消消乐一样,只不过这个开心消消乐是用栈实现的,题目里说如果遇到区间的左右端点是相同的,且区间内的元素大于端点那么就可以减去1,但其实我们可以一直操作到端点为0为止,所以我们就有了压栈的操作,但是必须要注意的是如果一旦有某个元素设为x,是小于顶元素的那么就是不能相消的,即顶元素是不能通过相消来实现的,所以一直弹出一直弹到顶元素是小于等于x,那么这时可以再次执行相消操作。
    最后的ans其实在还原这样一个事情 3 3 2 当3 3 减到2的时候其实是可以把第三个元素2一起消到0的,也就是说是有解的,所以我们检查到某个元素可以化为0的话,我们看他一开始的元素值和他相邻的不能化为0的元素值大小,如果不能化为0的元素值小于可以化为0的值那么他也可以被化为0。贪心推平确实如此