标签:数学,思维
思路
题目实际上可以转化为在不改变数组顺序的情况下删掉某些数,使得剩下的数组的价值与原数组相同,所以只需要找出有多少数可以删掉
先看一组例子,a1到a6分别为2,3,4,5,3,2,可以发现其中,a2=3,a3=4,a5=3能够删除,其实也就是单调区间中的数可以删掉,而区间边界,也就是拐点,是不能删掉的,因为删掉之后一定会导致价值变小(可以借助数轴理解),注意是变小,也就是说不存在前边删掉一个拐点使价值变小,然后后边又删掉一个拐点再将价值补回来这种情况,除了区间边界,数组的第一个和最后一个也不能删掉,这样只需要统计能删除的数的个数t,然后答案乘上2t(可以删也可以不删,每个数有两种选择)
还有一些特殊情况,那就是区间中会出现连续相等的数,比如4,2,2,2,4,这种情况3个2不能同时全部删除,所以这时候答案就要乘2t-1了
总结一下,对于1<i<=j<n,数组为a[i-1]<a[i]=…=a[j]<a[j+1]或者a[i-1]>a[i]=…=a[j]>a[j+1]的情况,a[i]到a[j]是可以全部删除的,其余情况就至少要保留一位数
代码实现
#include<stdio.h>
#include<iostream>
using namespace std;
const int N = 1e5 + 5;
const int mod = 998244353;
int t, book, n;
int a[N];
long long qpow(int x){
long long c = 1, d = 2;
while(x){
if(x&1) c = c*d%mod;
d = d*d%mod;
x = x >> 1;
}
return c;
}
int main(){
cin >> t;
while(t--){
long long ans = 1;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++){
int j = i;
while(a[i] == a[j+1]) j++; //找区间连续相等的数
if(i >= 2 && j <= n - 1 && ((a[i] > a[i-1] && a[i] < a[j+1]) || (a[i] < a[i-1] && a[i] > a[j+1]))){ //全部能删掉的情况
ans = ans*qpow(j - i + 1)%mod;
}else ans = ans*(qpow(j - i + 1) - 1)%mod;
i = j;
}
cout << ans << "\n";
}
return 0;
}