觀察一下題意就是讓你把排列分成兩個沒有逆序的序列,問方案數
那麼把每個逆序對連邊,容易發現如果是二分圖,答案就是2^(聯通塊數量),否則無解
那麼先把無解判掉,然後從前往後一個數一個數加入,因爲現在肯定有解了,所以對於同一個i和a[i],任意兩個滿足j<i,a[j]>a[i]的j和j',j和j'當前一定屬於兩個不同的聯通塊,而現在他們都要和i連邊,那麼把i加進來之後他們就都變成一個聯通塊了
而對於一個聯通塊,我們只需要保存其中最大的元素就可以,因爲第二大的元素永遠也不會再向後連邊了,如果第二大的還能向後連邊就說明無解
那麼從前往後掃一遍,每次加一個數之後把大於等於這個數的都刪掉,再把刪掉的數裏最大的加回來
最後剩的數的個數就是聯通塊的數量
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 100010
#define MAXM 1010
#define ll long long
#define eps 1e-8
#define MOD 998244353
#define INF 1000000000
#define lb(x) x&-x
set<int>s;
int c[MAXN];
int ans=1;
int n;
int ask(int x){
int re=0;
for(;x;x-=lb(x)){
re=max(re,c[x]);
}
return re;
}
void change(int x,int y){
for(;x<=n;x+=lb(x)){
c[x]=max(c[x],y);
}
}
int main(){
int i,x;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&x);
int t=ask(n-x);
if(t==2){
printf("0\n");
return 0;
}
change(n-x+1,t+1);
int mx=x;
set<int>::iterator p=s.upper_bound(x);
while(p!=s.end()){
mx=max(mx,*p);
set<int>::iterator tmp=p;
p++;
s.erase(tmp);
}
s.insert(mx);
}
x=s.size();
while(x){
(ans<<=1)%=MOD;
x--;
}
printf("%d\n",ans);
return 0;
}
/*
*/