关于如何思考DP这件事...这题还是比较好的
思路:考虑为当前共有 i 个数且以为结尾,能够形成的字段的个数。要想求出,只需要知道的前一个数可以是什么,这样就能够进行状态转移了。
首先定义是前方第一个比小的数。
1、首先考虑比还要大的数:如果一次操作中是最小的话,那么就能够删掉前面的数。因此的前一个数可以是。
2、接下来考虑的是比还要小的数,可以发现是可以被替换掉的。只需要找到前方第一个比它小的数,那么就会被替换掉。如此往复直到没有比它还要小的数为止。
接下来考虑如何去快速求解:
1、对于而言,需要找到前方第一个比还要小的数的下标,这一点可以用单调栈来实现。
2、对范围内的数,可以用前缀和来快速求解。
3、对于第二种情况,它并不是连续的一些数,但是可以发现这些数都是固定的,不会随着后面的数到来而改变,因此也可以化简成一个DP,从而快速转移。
最终考虑可达数组的个数:并不是以 i 结尾就一定能构成可达数组,必须要满足后方没有比它还要大的数才行,否则就永远不可能成为最终数组的最后一个,这个判断只需要反向整一个单调栈就行了。
// Problem: D. Array Collapse
// Contest: Codeforces - Educational Codeforces Round 160 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1913/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second
#define endl '\n'
#define int long long
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 998244353;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){return b > 0 ? gcd(b , a % b) : a;
}LL lcm(LL a , LL b){return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){for(int i = 0 ; i <= n ; i ++){a[i] = 0;}
}
void solve()
{int n;cin >> n;vector<int>dp(n + 5 , 0);vector<int>sum(n + 5 , 0);vector<int>dp2(n + 5 , 0);for(int i = 1 ; i <= n ; i ++)cin >> a[i];stack<pair<int,int>>st;vector<int>tl(n + 5 , 0);for(int i = 1 ; i <= n ; i ++){while(!st.empty()){auto tmp = st.top();if(a[i] < tmp.x){st.pop();}else{break;}}if(st.empty()){st.push({a[i] , i});tl[i] = 0;}else{auto tmp = st.top();tl[i] = tmp.y;st.push({a[i] , i});}}for(int i = 1 ; i <= n ; i ++){dp[i] = sum[i - 1] - sum[tl[i]];dp[i] += mod;if(tl[i] == 0){dp[i]++;}dp[i] += dp2[tl[i]];sum[i] = sum[i - 1] + dp[i];dp2[i] = dp2[tl[i]] + dp[i];dp[i] %= mod;sum[i] %= mod;dp2[i] %= mod;}int ans = 0;while(!st.empty()){st.pop();}for(int i = n ; i >= 1 ; i --){while(!st.empty()){auto tmp = st.top();if(a[i] < tmp.x){st.pop();}else{break;}}if(st.empty()){ans += dp[i];ans %= mod;st.push({a[i] , i});}else{st.push({a[i] , i});}}cout << ans << endl;//10//10 2///10 2 6 10 6//}
signed main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout.precision(10);int t=1;cin>>t;while(t--){solve();}return 0;
}